如何确定一个列表是否包含在另一个列表中,顺序是否相同(在Java中)?

时间:2012-03-28 14:22:30

标签: java collections arraylist

假设我有三个列表:

  

list1 = a,c,d,r,t

     

list2 = a,d,t

     

list3 = a,r,d

然后 list2 包含在 list1 中,但 list3 不是因为它的顺序不同。

我在Apache Commons中检查了isSubCollection() CollectionUtilscontainsAll()方法,但似乎他们不考虑订单。

4 个答案:

答案 0 :(得分:4)

boolean isSubsequence(List<?> sup, List<?> sub) {
    int current = 0;
    for (Object obj: sup) {
      if (current == sub.size()) {
         return true;
      }
      if (obj.equals(sub.get(current)) {
        current++;
      }
    }
    return current == sub.size();
}

此算法是线性的,在sup列表中只需要1次迭代。

<强>更新
如果使用链接列表,则get操作可以在O(n)中运行。所以你可以使用2个迭代器:

boolean isSubsequence(List<?> sup, List<?> sub) {
  Iterator<?> supIt = sup.iterator();
  for (Iterator<?> subIt = sub.iterator(); subIt.hasNext();) {
    Object current = subIt.next();
    boolean found = false;
    while (supIt.hasNext() && !found) {
      found |= supIt.next().equals(current);
    }
    if (!found) {
      return false;
    }
  }
  return true;
} 

但看起来更丑陋。

答案 1 :(得分:0)

效率不高但是......

您可以在list2中抓取一个项目并迭代list1,直到找到它或到达列表末尾。如果找到了,请将索引保存在找到它的位置。

在list2中前进,并从第一个索引前进迭代list1。

如果你到了list2的末尾,它就是你的标准的子列表。

如果你到了list1的末尾并没有exausted list2,那就不是。

答案 2 :(得分:0)

自己鞭打起来并不困难。

boolean isSubSequence(List<?> sup, List<?> sub) {
  for (Object o : sub) {
    int index = sup.indexOf(o);
    if (index == -1) { return false; }
    sup = sup.subList(index + 1, sup.size());
  }
  return true;
}

这需要时间O(sup.size()+ sub.size()),这通常是最佳的。

答案 3 :(得分:0)

此处所需的方法与语言无关,但您至少需要确保可能来实现您的Java目标。使用C或C ++语言中的指针更容易描述解决方案,但我会尝试在这里使用更通用的术语。

从“包含列表”的第一个字符和“包含列表”开始。

  • 如果两个字符匹配,则前进到两个列表的下一个字符。

    • 如果您到达“包含列表”的末尾,答案是肯定的, 包含在另一个列表中。

      否则,如果您到达“包含列表”的末尾,则答案为否,包含“包含列表”。

      否则,请使用两个当前当前字符重复此过程。

  • 否则,前进到“包含列表”的下一个字符,然后再次尝试“包含列表”的相同字符。

    • 如果到达“包含列表”的末尾,则答案为否,包含“包含列表”。

      否则,请使用两个当前当前字符重复此过程。

如果您在纸张上的每个列表中的字符上绘制两个箭头(“指针”),并且只有当它与“包含列表”中的字符匹配时才会将“包含列表”中的箭头向右碰撞,并且将每个步骤中的“包含列表”中的箭头向右移动,您将看到匹配成功与失败的可能性如何发挥作用。