简体   繁体   中英

Find missing numbers in array, time complexity O(N), space complexity O(1)

You are given an array of n unique integer numbers 0 <= x_i < 2 * n. Print all integers 0 <= x < 2 * n that are not present in this array.

Example:

find_missing([0]) = [1]

find_missing([0, 2, 4]) = [1, 3, 5] # because all numbers are [0, 1, 2, 3, 4, 5]

find_missing([]) = []

find_missing([0, 1, 4, 5]) = [2, 3, 6, 7] # because all numbers are [0, 1, 2, 3, 4, 5, 6, 7]

Quirks are about requirements:

Time complexity O(n) - BUT there should be some fixed constant C independent of size of input such that every element of array is written/read < C times, so radix sorting the array is a no go.

Space complexity O(1) - you may modify the initial array, BUT sorted(initial_array) must equal sorted(array_after_executing_program) AND you can't store integers outside range [0, 2n) in this array (imagine that it's an array of uint32_t).

I saw a lot of complex solutions, but then I found this:

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);
    }
}

I believe that is the best solution, but I am not sure. I would like to know why that would NOT work.

As @LasseV.Karlsen pointed out, [0,3] is a simple counter-example that shows how that solution doesn't work. This, however, is a pretty simple solution (in 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))

The idea is simple. We first rearrange the elements so that every value j that is less than n is stored at index j. We can then go through the array and easily pick out the ones below n that are missing.

We then rearrange the elements so that every value j that is greater than or equal to n is stored at index jn. Again, we can go through the array and easily pick out the ones greater than or equal to n that are missing.

Since only a couple of local variables are used, the O(1) space complexity is satisfied.

Because of the nested loops, the O(n) time complexity is a little harder to see, but it isn't too hard to show that we never swap more than n elements, since one new element is put into its proper place with each swap.

Since we've only swapped elements of the array, the requirement that all the original elements are still in the array is also satisfied.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM