Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find the first "missing" number in a sorted list

Let's say I have the continuous range of integers [0, 1, 2, 4, 6], in which the 3 is the first "missing" number. I need an algorithm to find this first "hole". Since the range is very large (containing perhaps 2^32 entries), efficiency is important. The range of numbers is stored on disk; space efficiency is also a main concern.

What's the best time and space efficient algorithm?

like image 283
zx_wing Avatar asked Jul 08 '12 19:07

zx_wing


People also ask

How do I find a missing element in a sorted array?

An efficient solution is to use binary search. We use the index to search for the missing element and modified binary search. If element at mid != index+1 and this is first missing element then mid + 1 is the missing element.


2 Answers

Use binary search. If a range of numbers has no hole, then the difference between the end and start of the range will also be the number of entries in the range.

You can therefore begin with the entire list of numbers, and chop off either the first or second half based on whether the first half has a gap. Eventually you will come to a range with two entries with a hole in the middle.

The time complexity of this is O(log N). Contrast to a linear scan, whose worst case is O(N).

like image 134
phs Avatar answered Sep 28 '22 09:09

phs


Based on the approach suggested by @phs above, here is the C code to do that:

#include <stdio.h>

int find_missing_number(int arr[], int len) {
    int first, middle, last;
    first = 0;
    last = len - 1;
    middle = (first + last)/2;

    while (first < last) {
        if ((arr[middle] - arr[first]) != (middle - first)) {
            /* there is a hole in the first half */
            if ((middle - first) == 1 && (arr[middle] - arr[first] > 1)) {
                return (arr[middle] - 1);
            }

            last = middle;
        } else if ((arr[last] - arr[middle]) != (last - middle)) {
            /* there is a hole in the second half */
            if ((last - middle) == 1 && (arr[last] - arr[middle] > 1)) {
                return (arr[middle] + 1);
            }

            first = middle;
        } else {
            /* there is no hole */
            return -1;
        }

        middle = (first + last)/2;
    }

    /* there is no hole */
    return -1;
}

int main() {
    int arr[] = {3, 5, 1};
    printf("%d", find_missing_number(arr, sizeof arr/(sizeof arr[0]))); /* prints 4 */
    return 0;
}
like image 20
nickhalden Avatar answered Sep 28 '22 10:09

nickhalden