4

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.

asked Apr 10, 2016 at 17:07
7
  • 1
    Since it doesn't do what you asked for, it is not a solution at all. Try passing in 0, 3. You'll get 3, 0 back, clearly it doesn't output the missing numbers at all. Commented Apr 10, 2016 at 17:13
  • Is the input guaranteed to be sorted, like it is in all the examples? Commented Apr 10, 2016 at 17:19
  • Is this the same as this question, stackoverflow.com/questions/3492302/… ? Commented Apr 10, 2016 at 17:23
  • It is not the same as that question, גלעד ברקן, as that other question only removed one number. That is a completely different question with an easy solution. This one here is different, where multiple numbers can be missing. The easy solution for that other question does not work here. Commented Apr 10, 2016 at 17:32
  • I see now that it breaks if two elements complement each other. I.E. if Max = 3, arr=[0, 3] 0+3 = 3 = Max. arr=[1,2] -> rs[2,1] and 2+1 = 3. Commented Apr 10, 2016 at 18:00

1 Answer 1

4

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 j-n. 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.

answered Apr 10, 2016 at 19:51
5
  • Can you explain why you first do numbers less than N, then numbers bigger than N? and in second loop, why "l[i]!=i+n" and not "l[i]!=i" Commented Apr 10, 2016 at 20:25
  • @user117325: We can't do both the larger and the smaller numbers at the same time because there would be conflicts. For example if l==[0,2]. Commented Apr 10, 2016 at 20:28
  • @user117325: In the second loop we are only considering values >= n. n is stored at index 0, n+1 is stored at index 1, etc. So that's why we're checking to see if l[i]!=l[i+n]. Commented Apr 10, 2016 at 20:32
  • The code by @YvesDaoust (above) does the same thing regarding the O(n) swap, but does not do it into two parts (less than N, bigger than N). Is there another example that would cause the conflict you describe? His solution might be missing that Commented Apr 10, 2016 at 21:19
  • 1
    @user117325: I don't think that answer is valid, since it relies on extending the original array. Commented Apr 10, 2016 at 21:34

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.