[英]How can I determine whether one list is contained in another, in the same order (in Java)?
Suppose I have three lists: 假设我有三个列表:
list1 = a, c, d, r, t
list1 = a,c,d,r,t
list2 = a, d, t
list2 = a,d,t
list3 = a, r, d
list3 = a,r,d
Then list2 is contained in list1 but list3 is not because it is not in the same order. 然后, list2包含在list1中,但list3不是,因为它的顺序不相同。
I checked isSubCollection()
from CollectionUtils
in Apache Commons, and the containsAll()
method, but it seems that they don't consider order. 我检查了Apache Commons中
CollectionUtils
isSubCollection()
和containsAll()
方法,但似乎它们不考虑顺序。
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();
}
This algorithm is linear and requires only 1 iteration in sup
list. 这种算法是线性的,只需要1次迭代
sup
列表。
UPDATE 更新
If you use linked lists, get
operation may run in O(n). 如果使用链接列表,则
get
操作可能在O(n)中运行。 So you can use 2 iterators: 因此,您可以使用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;
}
But it looks uglier. 但是看起来很丑。
Not very efficient but... 效率不高,但是...
You can grab one item in list2 and iterate list1 until you find it or you reach the end of the list. 您可以在list2中抓取一个项目并迭代list1,直到找到它或到达列表的末尾。 If you do find it, save the index where you found it.
如果找到它,请将索引保存在找到它的位置。
Advance in list2, and iterate list1 from the first index forward. 在list2中前进,并从第一个索引开始迭代list1。
If you get to the end of list2, it's a sub-list by your criteria. 如果到达list2的末尾,则根据您的条件,这是一个子列表。
If you get to the end of list1 and haven't exausted list2, it ain't. 如果您到达list1的末尾并且还没有浏览list2,则不是。
It's not too difficult to whip up on your own. 自己动手并不难。
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;
}
That takes time O(sup.size() + sub.size()), which is optimal in general. 这需要时间O(sup.size()+ sub.size()),这通常是最佳的。
The approach required here is the same independent of language, though you at least need to be sure that it's possible to achieve your goal in Java. 尽管您至少需要确保可以使用Java实现目标,但此处所采用的方法与语言无关,但它们相同。 The solution is easier to describe using pointers from the C or C++ language, but I'll try to use more general terms here.
使用C或C ++语言的指针更容易描述该解决方案,但是我将在这里尝试使用更通用的术语。
Start with the first character of the "containing list" and the "contained list." 从“包含列表”和“包含列表”的第一个字符开始。
If the two characters match, advance to the next character of both lists. 如果两个字符匹配,请前进到两个列表的下一个字符。
If you reached the end of the "contained list," the answer is yes, it is contained within the other list. 如果达到了结束“载列表中,”答案是肯定的,它包含在其他列表中。
Otherwise, if you reached the end of the "containing list," the answer is no, it does not contain the "contained list." 否则,如果到达“包含列表”的末尾,则答案为“否”,它不包含“包含列表”。
Otherwise, repeat the process with the two now-current characters. 否则,请使用两个当前字符重复该过程。
Otherwise, advance to the next character of the "containing list," and try again against the same character of the "contained list." 否则,请前进到“包含列表”的下一个字符,然后再次尝试对“包含列表”的相同字符。
If you reach the end of the "containing list," the answer is no, it does not contain the "contained list." 如果到达“包含列表”的末尾,则答案为否,它不包含“包含列表”。
Otherwise, repeat the process with the two now-current characters. 否则,请使用两个当前字符重复该过程。
If you draw two arrows ("pointers") to the characters in each list on paper, and only ever bump the arrow in the "contained list" to the right when it matches a character in the "containing list," and bump the arrow in the "containing list" to the right on every step, you'll see how the possibilities for matching success and failure play out. 如果您在纸上每个列表中的字符上绘制两个箭头(“指针”),并且只在与“包含列表”中的字符匹配时将“包含列表”中的箭头与右侧相碰,然后对箭头进行凹凸处理在每一步右侧的“包含列表”中,您将看到匹配成功和失败可能性的方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.