数组中的相同对是2个索引p,q
,这样
0<=p<q<N
和array[p]=array[q]
其中N
是数组的长度。
给定一个未排序的数组,找到数组中相同的数字对。
我的解决方案是按值对数组进行排序, 跟踪指数。
然后对于排序数组中的每个索引p
,计算所有q<N
以及
sortedarray[p].index < sortedarray[q].index and
sortedarray[p] = sortedarray[q]
这是正确的做法吗?我认为复杂性将是
O(N log N) for sorting based on value +
O(N^2) for counting the newsorted array that satisfies the condition.
这意味着我仍在关注O(N^2)
。还有更好的方法吗?
另一个想法是每个P二进制搜索满足条件的所有Q的排序数组。这不会将第二部分的复杂性降低到O(Nlog(N))
这是我的第二部分代码
for(int i=0;i<N;i++){
int j=i+1;
while( j<N && sortedArray[j].index > sortedArray[i].index &&
sortedArray[j].item == sortedArray[i].item){
inversion++;
j++;
}
}
return inversion;
@Edit:我想,我把第二部分的复杂性误认为是O(N^2)
。
与while循环中的每次迭代一样,不会发生索引0-i中元素的重新扫描,扫描排序后的数组以计算反转需要线性时间。因此总复杂度
O(NlogN)
用于排序,O(N)
用于排序数组中的线性扫描计数。
答案 0 :(得分:3)
你是部分正确的。通过Merge Sort或Heapsort对数组进行排序将需要O(n lg n)
。但是一旦对数组进行了排序,您可以进行单次传递以查找所有相同的对。此单次传递是O(n)
操作。所以总的复杂性是:
O(n lg n + n) = O(n lg n)
答案 1 :(得分:1)
Tim在回答中指出,在排序数组中查找对的复杂性为O(n)
而不是O(n^2)
。
为了说服自己,请考虑一个典型的O(n^2)
算法: Insertion Sort 。
可以找到动画示例here。
正如你在gif中看到的,这个算法是二次方的原因是因为,对于每个元素,它必须检查整个数组以确保这个元素必须去的地方(这个包括数组中的前一个元素!)。
另一方面,在你的情况下,你有一个有序数组:例如[0,1,3,3,6,7,7,9,10,10]
在这种情况下,你将从头开始扫描(成对),并且(因为数组是有序的)你知道一旦扫描了一个元素并且指针继续进行,就没有任何理由重新扫描以前的元素,因为否则你不会在第一时间进行。
因此,您只扫描整个数组一次:O(n)
答案 2 :(得分:0)
如果你可以分配更多的内存,你可以获得一些收益。
您可以使用哈希表到达O(n)
,该哈希表将数组中的任何值映射到计数器,指示您已经看到此值的频率。
如果允许值的数量是整数且在有限的范围内,则可以直接使用数组而不是哈希表。值i
的索引本身为i
。在这种情况下,复杂性为O(n+m)
,其中m
是允许值的数量(因为您必须首先将0
数组中的所有条目设置为nv_i
,然后查看所有数组条目数对)。
两种方法都为您提供了数组中每个值的相同值的数量。我们将此数字i
称为数组中值i
的出现次数。然后,值(nv_i)*(nv_i-1)/2
对的数量为:1st i with nv_i-1 others
2nd i with nv_i-2 others
...
last i with 0
。
你可以配对:
(nv_i-1)+(nv_i-2)+...+0 = (nv_i)*(nv_i-1)/2
{{1}}
答案 3 :(得分:0)
我一直在想这个....我想如果你&#34;嵌入&#34;然后,==
条件进入排序算法,复杂度仍为O(n lg n)。