![](/img/trans.png)
[英]Alternative O(N^2) time complexity with O(1) space complexity for finding distinct values in array
[英]Find missing numbers in array, time complexity O(N), space complexity O(1)
给出一个n个唯一整数0 <= x_i <2 * n的数组。 打印此数组中不存在的所有整数0 <= x <2 * n。
例:
find_missing([0])= [1]
find_missing([0,2,4])= [1,3,5]#因为所有数字都是[0,1,2,3,4,5]
find_missing([])= []
find_missing([0,1,4,5])= [2,3,6,7]#因为所有数字都是[0,1,2,3,4,5,6,7]
怪癖是关于要求:
时间复杂度O(n) - 但是应该有一些与输入大小无关的固定常数C,这样数组的每个元素都被写入/读取<C次,所以对数组进行基数排序是不行的。
空间复杂度O(1) - 你可以修改初始数组,BUT sorted(initial_array)必须等于sort(array_after_executing_program)并且你不能在这个数组中存储范围[0,2n]之外的整数(想象它是uint32_t的数组) )。
我看到了很多复杂的解决方案,但后来我发现了这个:
public void printNotInArr(int[] arr) {
if(arr == null)
return null;
int len = arr.length;
int max = 2 * len;
for(int i = 0; i < len; i++) {
System.out.println(max - arr[i] - 1);
}
}
我相信这是最好的解决方案,但我不确定。 我想知道为什么那不起作用。
正如@ LasseV.Karlsen指出的那样,[0,3]是一个简单的反例,展示了该解决方案不起作用的方式。 然而,这是一个非常简单的解决方案(在Python中):
def show_missing(l):
n = len(l)
# put numbers less than n into the proper slot
for i in range(0,n):
while l[i]<n and l[i]!=i:
j = l[i]
l[i] = l[j]
l[j] = j
for i in range(0,n):
if l[i]!=i:
print('Missing %s'%i)
# put numbers greater than n into the proper slot
for i in range(0,n):
while l[i]>=n and l[i]!=i+n:
j = l[i]
l[i] = l[j-n]
l[j-n] = j
for i in range(0,n):
if l[i]!=i+n:
print('Missing %s'%(i+n))
这个想法很简单。 我们首先重新排列元素,以便每个小于n的值j存储在索引j处。 然后我们可以通过数组并轻松挑选出缺少的n以下的数组。
然后,我们重新排列元素,使得大于或等于n的每个值j都存储在索引jn处。 同样,我们可以通过数组并轻松挑选出大于或等于n的数组。
由于仅使用几个局部变量,因此满足O(1)空间复杂度。
由于嵌套循环,O(n)时间复杂度有点难以看出,但是要表明我们从不交换n个元素并不太难,因为一个新元素被放入其适当的位置交换。
由于我们只交换了数组的元素,因此也满足了所有原始元素仍在数组中的要求。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.