我有一个简单的问题,需要找到数组A中第一个唯一的元素。但是,困扰我的是使用不同方法的时间复杂度。到目前为止,我已经尝试了这两种方法。
第一种方法:
第二种方法:
编辑:
消耗了99%的执行时间,而
始终为1-3毫秒。所以,是的,填充地图是最昂贵的操作。
您会建议哪种方法对于这种问题最有效?
第一种方法:
LinkedHashMap<Integer, List<Integer>> map = new LinkedHashMap<Integer, List<Integer>>();
for (int i = 0; i < A.length; i++)
{
if (!map.containsKey(A[i]))
map.put(A[i], new ArrayList<>());
map.get(A[i]).add(i);
}
for (Map.Entry<Integer, List<Integer>> m : map.entrySet())
if (m.getValue().size() == 1)
return m.getKey();
return -1;
第二种方法:
for(int i=0; i< A.length; i++){
boolean unique = true;
nestedFor:for(int j=0; j< A.length; j++){
if(i != j && A[i] == A[j]){
unique = false;
break nestedFor;
}
}
if(unique)
return A[i];
}
return -1;
使用一个1000000个元素的数组进行测试,第一种方法执行时间约为2000毫秒,而第二种方法执行时间约为10毫秒。我的问题是:第一种方法的复杂度为O(nLogn),比第二种方法的复杂度O(n^2)更快,应该执行得更快,我错在哪里了?以下是测试代码:
int[] n = new int[1000000];
for (int i = 0; i < n.length; i++)
n[i] = new Random().nextInt(2000000);
long start = System.currentTimeMillis();
firstUnique(n);
System.err.println("Finished at: " + (System.currentTimeMillis() - start ) + "ms");
编辑:
for (int i = 0; i < A.length; i++)
{
if (!map.containsKey(A[i]))
map.put(A[i], new ArrayList<>());
map.get(A[i]).add(i);
}
消耗了99%的执行时间,而
for (Map.Entry<Integer, List<Integer>> m : map.entrySet())
if (m.getValue().size() == 1)
return m.getKey();
始终为1-3毫秒。所以,是的,填充地图是最昂贵的操作。
您会建议哪种方法对于这种问题最有效?
A
是int []
,则您在那里没有这个开销... - BeyelerStudiosfor (int j = i + 1; ...)
来使第二种方法的速度大约快两倍(在最坏情况下)。不仅可以遍历一半的元素,还可以跳过i != j
检查。 - Andy Turner