Easy interview question got harder: given numbers 1..100, find the missing number(s) given exactly k are missing

前端 未结 30 1126
时光说笑
时光说笑 2020-11-22 07:02

I had an interesting job interview experience a while back. The question started really easy:

Q1: We have a bag containing numbers

相关标签:
30条回答
  • 2020-11-22 07:40

    For Q2 this is a solution that is a bit more inefficient than the others, but still has O(N) runtime and takes O(k) space.

    The idea is to run the original algorithm two times. In the first one you get a total number which is missing, which gives you an upper bound of the missing numbers. Let's call this number N. You know that the missing two numbers are going to sum up to N, so the first number can only be in the interval [1, floor((N-1)/2)] while the second is going to be in [floor(N/2)+1,N-1].

    Thus you loop on all numbers once again, discarding all numbers that are not included in the first interval. The ones that are, you keep track of their sum. Finally, you'll know one of the missing two numbers, and by extension the second.

    I have a feeling that this method could be generalized and maybe multiple searches run in "parallel" during a single pass over the input, but I haven't yet figured out how.

    0 讨论(0)
  • 2020-11-22 07:40

    I believe I have a O(k) time and O(log(k)) space algorithm, given that you have the floor(x) and log2(x) functions for arbitrarily big integers available:

    You have an k-bit long integer (hence the log8(k) space) where you add the x^2, where x is the next number you find in the bag: s=1^2+2^2+... This takes O(N) time (which is not a problem for the interviewer). At the end you get j=floor(log2(s)) which is the biggest number you're looking for. Then s=s-j and you do again the above:

    for (i = 0 ; i < k ; i++)
    {
      j = floor(log2(s));
      missing[i] = j;
      s -= j;
    }
    

    Now, you usually don't have floor and log2 functions for 2756-bit integers but instead for doubles. So? Simply, for each 2 bytes (or 1, or 3, or 4) you can use these functions to get the desired numbers, but this adds an O(N) factor to time complexity

    0 讨论(0)
  • 2020-11-22 07:41

    As @j_random_hacker pointed out, this is quite similar to Finding duplicates in O(n) time and O(1) space, and an adaptation of my answer there works here too.

    Assuming that the "bag" is represented by a 1-based array A[] of size N - k, we can solve Qk in O(N) time and O(k) additional space.

    First, we extend our array A[] by k elements, so that it is now of size N. This is the O(k) additional space. We then run the following pseudo-code algorithm:

    for i := n - k + 1 to n
        A[i] := A[1]
    end for
    
    for i := 1 to n - k
        while A[A[i]] != A[i] 
            swap(A[i], A[A[i]])
        end while
    end for
    
    for i := 1 to n
        if A[i] != i then 
            print i
        end if
    end for
    

    The first loop initialises the k extra entries to the same as the first entry in the array (this is just a convenient value that we know is already present in the array - after this step, any entries that were missing in the initial array of size N-k are still missing in the extended array).

    The second loop permutes the extended array so that if element x is present at least once, then one of those entries will be at position A[x].

    Note that although it has a nested loop, it still runs in O(N) time - a swap only occurs if there is an i such that A[i] != i, and each swap sets at least one element such that A[i] == i, where that wasn't true before. This means that the total number of swaps (and thus the total number of executions of the while loop body) is at most N-1.

    The third loop prints those indexes of the array i that are not occupied by the value i - this means that i must have been missing.

    0 讨论(0)
  • 2020-11-22 07:45

    Here's a solution that uses k bits of extra storage, without any clever tricks and just straightforward. Execution time O (n), extra space O (k). Just to prove that this can be solved without reading up on the solution first or being a genius:

    void puzzle (int* data, int n, bool* extra, int k)
    {
        // data contains n distinct numbers from 1 to n + k, extra provides
        // space for k extra bits. 
    
        // Rearrange the array so there are (even) even numbers at the start
        // and (odd) odd numbers at the end.
        int even = 0, odd = 0;
        while (even + odd < n)
        {
            if (data [even] % 2 == 0) ++even;
            else if (data [n - 1 - odd] % 2 == 1) ++odd;
            else { int tmp = data [even]; data [even] = data [n - 1 - odd]; 
                   data [n - 1 - odd] = tmp; ++even; ++odd; }
        }
    
        // Erase the lowest bits of all numbers and set the extra bits to 0.
        for (int i = even; i < n; ++i) data [i] -= 1;
        for (int i = 0; i < k; ++i) extra [i] = false;
    
        // Set a bit for every number that is present
        for (int i = 0; i < n; ++i)
        {
            int tmp = data [i];
            tmp -= (tmp % 2);
            if (i >= even) ++tmp;
            if (tmp <= n) data [tmp - 1] += 1; else extra [tmp - n - 1] = true;
        }
    
        // Print out the missing ones
        for (int i = 1; i <= n; ++i)
            if (data [i - 1] % 2 == 0) printf ("Number %d is missing\n", i);
        for (int i = n + 1; i <= n + k; ++i)
            if (! extra [i - n - 1]) printf ("Number %d is missing\n", i);
    
        // Restore the lowest bits again.
        for (int i = 0; i < n; ++i) {
            if (i < even) { if (data [i] % 2 != 0) data [i] -= 1; }
            else { if (data [i] % 2 == 0) data [i] += 1; }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 07:45

    You could try using a Bloom Filter. Insert each number in the bag into the bloom, then iterate over the complete 1-k set until reporting each one not found. This may not find the answer in all scenarios, but might be a good enough solution.

    0 讨论(0)
  • 2020-11-22 07:45

    I think this can be generalized like this:

    Denote S, M as the initial values for the sum of arithmetic series and multiplication.

    S = 1 + 2 + 3 + 4 + ... n=(n+1)*n/2
    M = 1 * 2 * 3 * 4 * .... * n 
    

    I should think about a formula to calculate this, but that is not the point. Anyway, if one number is missing, you already provided the solution. However, if two numbers are missing then, let's denote the new sum and total multiple by S1 and M1, which will be as follows:

    S1 = S - (a + b)....................(1)
    
    Where a and b are the missing numbers.
    
    M1 = M - (a * b)....................(2)
    

    Since you know S1, M1, M and S, the above equation is solvable to find a and b, the missing numbers.

    Now for the three numbers missing:

    S2 = S - ( a + b + c)....................(1)
    
    Where a and b are the missing numbers.
    
    M2 = M - (a * b * c)....................(2)
    

    Now your unknown is 3 while you just have two equations you can solve from.

    0 讨论(0)
提交回复
热议问题