Java 从ArrayList中删除子列表

Java 从ArrayList中删除子列表,java,arraylist,Java,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 有没有办法做到这一点?使用 ListiTror < /C>对我来说似乎不起作用,因为我必须集体考虑三个连续的元素,而且我真的不知道该怎么做。 以下是我实现的方法的框架: public static void filterList(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
有没有办法做到这一点?使用<代码> ListiTror < /C>对我来说似乎不起作用,因为我必须集体考虑三个连续的元素,而且我真的不知道该怎么做。 以下是我实现的方法的框架:

public static void filterList(ArrayList<Integer> list) {
    ListIterator<Integer> iterator = list.listIterator();
    int elem; 
    while (iterator.hasNext()) {
        // Remove any sublist of 6 0 6
    }
}
publicstaticvoidfilterlist(数组列表){
ListIterator迭代器=list.ListIterator();
内因;
while(iterator.hasNext()){
//删除6 0 6的任何子列表
}
}

编辑:同样,为了简单起见,我们假设不会出现60606或类似的情况

我建议您先搜索
数组列表
,然后再将其放入
列表迭代器

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
    }
}
publicstaticvoidfilterlist(数组列表){
bool firstInstance=false;//表示已找到子列表的第一个实例

对于(int i=0;i,您可以使用以下方法创建高效简洁的O(nm)解决方案:

publicstaticvoidremoveallsublist(列表列表,列表子列表){
//查找列表中第一个出现的子列表,O(nm)
int i=Collections.indexofpublist(列表,子列表);
//如果找到
如果(i!=-1){
//批量移除,O(m)
list.subList(i,i+subList.size()).clear();
//与列表的其余部分一起递归
removeAllSubList(list.subList(i,list.size()),subList);
}
}

[编辑-更好的单通道方法]

自定义、增强的
indexofpublist
offset
开始搜索;因此,我们不会在每次删除某个内容时从
0
重新启动(就像我们使用
集合时所做的那样。indexofpublist
请参阅此答案的底部)

static int indexofpublist(列表干草堆、列表指针、int偏移量){
int toRet=-1;
int-needlen=needle.size();
如果(针>0){
//搜索是有意义的
int haystackLen=haystack.size();
对于(;偏移量+针距=0;
ixOfNeedle=Collections.IndexOfPublist(干草堆,针)
) {
对于(int i=needle.size();i>0;i--){
草垛。移除(针的IX);
}
}
}

您可以使用数组和列表组合作为以下解决方案,希望对您有所帮助

    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);
        }
    }
public void testData()
{
int tempArray[]={6,4,5,6,0,6,3,4,1,6,1,6,0,6,8,3};
List resultArray=new ArrayList();
for(int i=0;i

注意:您可以在上述函数中根据您的要求传递数组或返回结果。

为什么不能使用
list.removeAll(子列表)
如果输入是60606会是什么情况?@Naruto对于这个例子来说并不重要。我只是想说明这个想法。@Sam将删除所有出现的
6
0
。它不会强制执行3个数字的顺序。@4castle ya你是对的。。但是如果子列表包含元素(6 0 6)这听起来是一个很好的解决方案。你介意展示代码供我和其他人参考吗?如果它有效,我会将答案标记为已接受。“这将是一个O(n)解决方案”真的吗?我等不及你发表你在计算机科学方面的突破性进展了,@Adriancolomithi如果它总是搜索
606
,如果它搜索任何可变长度的子列表,那么它将是O(nm),或者更好,如果使用您链接到的其中一种算法。@fireyphoenix我已经用代码更新了代码以供参考。如果您只需要删除
6,0,6
,您应该进行一些优化。在查看了@Adriancolomychi的解决方案的潜在效率后,我的答案完全不同。
list.remove(I);list.remove(i+1);list.remove(i+2);
->
list.remove(i);list.remove(i);list.remove(i);
谢谢,现在已经太迟了。我会立即进行调整。虽然易于阅读,但在较大的列表中这将非常低效O(mn^2)。您应该使用@4castle-这个如何?O(n*m/2)在一般情况下,假设随机len匹配在haystack中,子字符串为pinder。我说得有点太早了,因为我们没有一个方法可以从某个索引开始。使用
List#subList
是我想要改进它的方法,因为你可以通过缩小你给出的列表来指定一个新的开始索引。这里当您已经可以使用第一个参数的
子列表
来指定起始索引时,就不需要编写
indexofpublist
的自定义实现。
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);
    }
  }
}
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);
      }
    }
}
    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);
        }
    }