簡體   English   中英

在數組中找到缺少的數字,時間復雜度O(N),空間復雜度O(1)

[英]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(ini​​tial_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM