我必须在两个列表中找到一些常见项目。我无法排序,顺序很重要。必须在secondList
中找到firstList
中出现的元素数量。现在看起来如下:
int[] firstList;
int[] secondList;
int iterator=0;
for(int i:firstList){
while(i <= secondList[iterator]/* two conditions more */){
iterator++;
//some actions
}
}
此算法的复杂性为 n x n 。我尝试降低此操作的复杂性,但我不知道如何以不同的方式比较元素?有什么建议吗?
修改
示例:A=5,4,3,2,3
B=1,2,3
我们寻找对B[i],A[j]
条件:
什么时候
B[i] < A[j]
j++
何时
B[i] >= A[j]
return B[i],A[j-1]
下一次遍历 A 列表到 j-1 元素(均值为for(int z=0;z<j-1;z++)
)
我不确定,我是否清楚了?
允许重复。
答案 0 :(得分:5)
我的方法是 - 将第一个数组中的所有元素放在HashSet
中,然后对第二个数组进行迭代。这降低了两个阵列长度之和的复杂性。它有额外内存的缺点,但除非你使用更多的内存我不认为你可以改善你的暴力解决方案。
编辑:避免就此事发生进一步争议。如果允许第一个数组中有重复项,并且您实际关心第二个数组中的元素与第一个数组中的数组匹配多少次,请使用HashMultiSet
。
答案 1 :(得分:3)
解决时间小于n x n!
编辑以取悦fge:)
您可以使用带有项目的关键字和作为值的出现次数来代替集合。
然后对于第二个列表中的每个项目,如果它存在于地图中,则在第一个列表(字典条目的值)中每次出现都执行一次。
答案 2 :(得分:1)
import java.util.*;
int[] firstList;
int[] secondList;
int iterator=0;
HashSet hs = new HashSet(Arrays.asList(firstList));
HashSet result = new HashSet();
while(i <= secondList.length){
if (hs.contains( secondList[iterator]))
{
result.add(secondList[iterator]);
}
iterator++;
}
结果将包含必需的公共元素。 算法复杂度n
答案 3 :(得分:1)
仅仅因为订单很重要并不意味着您无法对列表(或两者)进行排序。它只表示您必须先复制才能对任何内容进行排序。当然,复制需要额外的内存和排序需要额外的处理时间......但我想所有优于O(n ^ 2)的解决方案都需要额外的内存和处理时间(对于建议的HashSet解决方案也是如此 - 添加所有值到HashSet需要额外的内存和处理时间。)
可以在O(n * log n)时间内对两个列表进行排序,一旦列表被排序,可以在O(n)时间内查找公共元素。它是否比你的原生O(n ^ 2)方法更快取决于列表的大小。最后,只测试不同的方法可以告诉您哪种方法最快(并且那些测试应该使用在最终代码中预期的实际列表大小)。
Big-O符号不是告诉你任何关于绝对速度的符号,它只告诉你一些关于相对速度的信息。例如。如果你有两个算法来计算一组输入元素的值,一个是O(1)而另一个是O(n),这并不意味着O(1)解决方案总是更快。这是对Big-O符号的一个很大误解!它只意味着如果输入元素的数量加倍,O(1)解决方案仍然需要大约。 O(n)解决方案需要大约相同的时间。时间是以前的两倍。因此毫无疑问,通过不断增加输入元素的数量,必须有一个点,O(1)解决方案将变得比O(n)解决方案更快,但对于非常小的元素集合,O( 1)解决方案实际上可能比O(n)解决方案慢。
答案 4 :(得分:0)
好的,如果第一个或第二个数组中没有重复项,此解决方案将起作用。由于问题没有说明,我们无法确定。
首先,从第一个数组中构建LinkedHashSet<Integer>
,从第二个数组中构建HashSet<Integer>
。
其次,仅在第一组中保留第二组中的元素。
第三,迭代第一组并继续:
// A LinkedHashSet retains insertion order
Set<Integer> first = LinkedHashSet<Integer>(Arrays.asList(firstArray));
// A HashSet does not but we don't care
Set<Integer> second = new HashSet<Integer>(Arrays.asList(secondArray));
// Retain in first only what is in second
first.retainAll(second);
// Iterate
for (int i: first)
doSomething();