以下代码试图通过覆盖重复的元素来从排序的数组中删除重复项。虽然它嵌套了for循环,但它的复杂性肯定小于O(n ^ 2)。以下代码的复杂性是什么?
int n = arr.length;
for(int i=0;i<n;i++){
if(arr[i]==arr[i+1]){
for(int j=i+1;j<n-1;j++){
arr[j]=arr[j+1];
}
n--; i--;
}
}
答案 0 :(得分:1)
让我们从第一个位置开始。它肯定不会重复,所以你不做任何动作。然后我们进入第二个位置。它可以从第一个位置值复制,然后,它可能不是。如果是,那么你必须将它移动到最后,因此,对于前两个位置,你有两个场景,一个只是通过数组移动(它不重复),第二个是移动元素到数组的末尾,需要n-2
的{{1}}次操作。
现在,如果我们将第三个值移到第二个位置,我们仍然在它上面(arr[j]=arr[j+1]
部分)。它可以是第一个值的副本,也许不是。对于第一个选项,您必须执行i--
(因为您执行了n-3
,因此您将其从位置n--
移动到位置2
)n-1
的操作。现在,如果第二个值不是第一个值的重复(所以你没有arr[j]=arr[j+1]
和i--
),但第三个值是前两个值之一的重复,你仍然需要做{{ 1}} n--
的操作(从位置n-3
到位置arr[j]=arr[j+1]
)。因此,每种情况下的操作次数保持不变。
所以,我们在这里有一个模式:动态的3
。这笔款项是:
n
基于此,由于第一部分正在通过数组移动,即n-2 + n-3 + n -4 + ... + 3 + 2 + 1
,因此该算法的复杂度为n-2 + n-3 + n -4 + ... + 3 + 2 + 1 = n(n+1)/2 - n - n + 1
。最糟糕的情况是在数组中具有所有相同的值。
现在,有一种更好的方法。将所有值都放在O(n)
中。这需要移动数组(O(n^2)
),并检查Set中是否存在某些内容,即Set
。然后从O(n)
获取所有结果,并将它们放在数组中,即O(1)
。因此,此类算法的复杂性为Set
。