2016-09-26 5 views
3

Для простоты предположим, что у меня есть ArrayList, индексы которого содержат ровно одно однозначное целое число. Например:Удаление подписок из ArrayList

6 4 5 6 0 6 3 4 1 6 1 6 0 6 8 3 

Я хотел бы, чтобы отфильтровать все вхождения подсписке 6 0 6, таким образом, что новый список становится:

6 4 5 3 4 1 6 1 8 3 

Есть ли способ сделать это? Использование ListIterator, похоже, не работает для меня, потому что я должен рассматривать три последовательных элемента вместе, и я честно не знаю, как это сделать.

Вот скелет метода я реализовал:

public static void filterList(ArrayList<Integer> list) { 
    ListIterator<Integer> iterator = list.listIterator(); 
    int elem; 
    while (iterator.hasNext()) { 
     // Remove any sublist of 6 0 6 
    } 
} 

Edit: Опять же, для простоты, давайте предположим, что не будет иметь место случаи, когда мы имеем 60606 или аналогичный.

+0

Почему нельзя использовать 'list.removeAll (подсписок)' –

+0

Что будет, если вход 60606? – Naruto

+0

@Naruto Для этого не имеет значения. Я только пытался проиллюстрировать эту идею. –

ответ

2

Вы можете создать решение (нм) эффективное и сжатое O с помощью Collections.indexOfSubList:

public static void removeAllSubList(List<?> list, List<?> subList) { 
    // find first occurrence of the subList in the list, O(nm) 
    int i = Collections.indexOfSubList(list, subList); 
    // if found 
    if (i != -1) { 
     // bulk remove, O(m) 
     list.subList(i, i + subList.size()).clear(); 
     // recurse with the rest of the list 
     removeAllSubList(list.subList(i, list.size()), subList); 
    } 
} 

Ideone Demo

+0

Это похоже на красивое решение. Не могли бы вы показать код для моей справки и других? Если это сработает, я помечаю ответ как принятый. –

+0

", что это было бы решение O (n)" Действительно?Я просто не могу дождаться, когда вы опубликуете свои новаторские достижения в области компьютерных наук, [многие другие не смогли сделать это в O (N)] (https://en.wikipedia.org/wiki/String_searching_algorithm#Basic_classification). –

+0

@AdrianColomitchi Это было бы O (n), если бы он всегда искал '606', если он искал любой подсписчик переменной длины, тогда это будет O (nm), или лучше, если вы используете один из тех алгоритмов, которые вы связали к. – 4castle

0

Что я рекомендую - вам нужно поискать ArrayList, прежде чем превращать его в ListIterator.

public static void filterList(ArrayList<Integer> list) { 
    bool firstInstance = false; //Saying we having found our first instance of our sub list 
    for(int i=0;i<list.size();++i) { 
     if(list.get(i) == 6) //Checks to see if our first index is a 6 or it pointless to check the next two numbers i.e. wasting resources 
     if(list.get(i+1) == 0 && list.get(i+2) == 6 && !firstInstance) { //Make sure it a 6 0 6 list 
      list.remove(i); //Removes first one 
      list.remove(i); //Removes second one which now became our current index number 
      list.remove(i); //Removes third one which now became our current index number 
     } else 
      firstInstance = true; //Our first instances has been found and will now remove duplicate ones! 
    } 
    ListIterator<Integer> iterator = list.listIterator(); 
    int elem; 
    while (iterator.hasNext()) { 
     // Remove any sublist of 6 0 6-- Already Done 
    } 
} 
+1

'list.remove (i); list.remove (I + 1); list.remove (i + 2); '->' list.remove (i); list.remove (я); list.remove (i); ' – saka1029

+0

Спасибо, это слишком поздно для этого. Я сделаю эту настройку сразу. – Matthew

2

[Отредактировано - лучше, однопроходный подход]

на заказ, расширенный indexOfSublist, начинающийся с offset; поэтому мы не перезапускаем с 0 каждый раз, когда мы удаляем что-то (как это было при использовании Collections.indexOfSublist, см. нижнюю часть этого ответа).

static <T> int indexOfSublist(List<T> haystack, List<T> needle, int offset){ 
    int toRet=-1; 
    int needleLen=needle.size(); 
    if(needleLen>0) { 
    // it makes sense to search 
    int haystackLen=haystack.size(); 
    for(;offset+needleLen<haystackLen && toRet<0; offset++) { 
     int compIx; 
     for(
      compIx=0; 
      (
       compIx<needleLen 
       && false==haystack.get(offset+compIx).equals(needle.get(compIx)) 
     ); 
      compIx++ 
    ); 
     if(compIx==needleLen) { // found 
     toRet=offset; 
     } 
    } 
    } 
    return toRet; 
} 

public static void filterList(List<Integer> haystack, List<Integer> needle) { 
    for(
     int offset=0, ixOfNeedle=indexOfSublist(haystack, needle, offset); 
     ixOfNeedle>=0; 
     ixOfNeedle=indexOfSublist(haystack, needle, offset) 
) { 
    // found one place. We'll continue searching from here next time 
    offset=ixOfNeedle; 
    ////////////////////////////////////////// 
    // for a better removal sequence, see the 
    // 4castle's answer using sublists 
    for(int i=needle.size(); i>0; i--) { 
     haystack.remove(ixOfNeedle); 
    } 
    } 
} 

Collections.indexOfSublist является то, что вы после этого.

public static void filterList(ArrayList<Integer> haystack, List<Integer> needle) { 
    for(
     int ixOfNeedle=Collections.indexOfSublist(haystack, needle); 
     ixOfNeedle>=0; 
     ixOfNeedle=Collections.indexOfSublist(haystack, needle) 
    ) { 
     for(int i=needle.size(); i>0; i--) { 
     haystack.remove(ixOfNeedle); 
     } 
    } 
} 
+0

Хотя это легко читать, это будет очень неэффективно в больших списках O (mn^2). Вы должны оптимизировать его, используя ['List # subList'] (http://docs.oracle.com/javase/8/docs/api/java/util/List.html#subList (int,% 20int)). – 4castle

+0

@ 4castle - как насчет этого? O (n * m/2) в среднем случае - при условии, что случайные совпадения len в стоге сена с подстроками иглы. –

+0

Я говорил слишком рано, когда сказал, что у нас нет метода, который может начинаться с определенного индекса. Использование 'List # subList' состояло в том, как я планировал его улучшить, поскольку вы можете указать новый начальный индекс, просто сужая список, который вы ему даете. – 4castle

0

Вы можете использовать комбинацию элементов массива и списка, чтобы найти это решение ниже, надеясь, что это вам поможет.

public void testData() 
    { 
     int tempArray[] = {6, 4, 5, 6, 0, 6, 3, 4, 1, 6, 1, 6, 0, 6, 8, 3}; 
     List<Integer> resultArray = new ArrayList<>(); 

     for(int i = 0; i < tempArray.length; i++) 
     { 
      if(tempArray[i] == 6 && tempArray[i+1] == 0 && tempArray[i + 2] == 6) 
      { 
       i += 2; 
      } 
      else 
      { 
       resultArray.add(tempArray[i]); 
      } 
     } 

     for(int tempInt : resultArray) 
     { 
      System.out.print("\t" + tempInt); 
     } 
    } 

Примечание: Вы можете передать массив с вашей стороны или возвращает результат согласно вашему требованию в приведенной выше функции.

Смежные вопросы