HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaModerate

First missing positive with only primitives

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withprimitivesfirstmissingpositiveonly

Problem

As soon as I saw the First missing positive question, I decided to write my own method for this before writing my review on the question.

Judge me by the same standards as bazang wants to be judged, i.e. As if this was written for a big company such as Google for an interview.

I wasn't sure how the input 7, 8, 9 should be treated so to make it a bit harder for myself I gave myself the requirement that it should return 10.

@Test
public void test() {
    Assert.assertEquals(3, missingInt(new int[]{ 1, 2, 0 }));
    Assert.assertEquals(4, missingInt(new int[]{ 1, 2, 3 }));
    Assert.assertEquals(2, missingInt(new int[]{ 3, 4, -1, 1 }));
    Assert.assertEquals(10, missingInt(new int[]{ 7, 8, 9 }));

    Assert.assertEquals(5, missingInt(new int[]{ 3, 4, 2, 7, 6, 1 }));
    Assert.assertEquals(5, missingInt(new int[]{ 3, 4, 2, 7, 6, 1, -4 }));
}

public int missingInt(int[] array) {
    boolean[] foundIntegers = new boolean[array.length];
    int smallestPositive = Integer.MAX_VALUE;

    for (int i : array) {
        if (i > 0 && i < smallestPositive)
            smallestPositive = i;
    }

    for (int i : array) {
        if (i < smallestPositive)
            continue;

        int index = i - smallestPositive;
        if (index < foundIntegers.length)
            foundIntegers[index] = true;
    }

    for (int i = 0; i < foundIntegers.length; i++) {
        if (!foundIntegers[i])
            return i + smallestPositive;
    }
    return foundIntegers.length + smallestPositive;
}

Solution

Stupid edge-cases!

While doing some testing for coming up with a better version for the First missing positive question, I added a bunch of more test cases and compared several different methods with each other. Then I found the following problems:

Input [-5] returned 2147483647 but expected 1
Input [-5, -4, -3] returned 2147483647 but expected 1
Input [0, 0, 0, 0] returned 2147483647 but expected 1
Input [] returned 2147483647 but expected 1


To correct these problems, I added some edge-case checking; to check for array where there are no positive integers. As these really are edge-cases, I haven't decided how to handle these. As there technically isn't a clear "first missing positive number". If I would have handled 7 8 9 as return 1 then I would have returned 1 for these edge cases also, but I feel that wouldn't be expected behavior from this algorithm so therefore I decided to throw an exception.

The new code is:

public int simonNew(int[] array) {
    boolean[] foundIntegers = new boolean[array.length];
    int smallestPositive = Integer.MAX_VALUE;

    for (int i : array) {
        if (i > 0 && i < smallestPositive)
            smallestPositive = i;
    }
    if (smallestPositive == Integer.MAX_VALUE)
        throw new IllegalArgumentException("Array must not be null and must contain at least one positive integer");

    for (int i : array) {
        if (i < smallestPositive)
            continue;

        int index = i - smallestPositive;
        if (index < foundIntegers.length)
            foundIntegers[index] = true;
    }

    for (int i = 0; i < foundIntegers.length; i++) {
        if (!foundIntegers[i])
            return i + smallestPositive;
    }
    return foundIntegers.length + smallestPositive;
}

Code Snippets

Input [-5] returned 2147483647 but expected 1
Input [-5, -4, -3] returned 2147483647 but expected 1
Input [0, 0, 0, 0] returned 2147483647 but expected 1
Input [] returned 2147483647 but expected 1
public int simonNew(int[] array) {
    boolean[] foundIntegers = new boolean[array.length];
    int smallestPositive = Integer.MAX_VALUE;

    for (int i : array) {
        if (i > 0 && i < smallestPositive)
            smallestPositive = i;
    }
    if (smallestPositive == Integer.MAX_VALUE)
        throw new IllegalArgumentException("Array must not be null and must contain at least one positive integer");

    for (int i : array) {
        if (i < smallestPositive)
            continue;

        int index = i - smallestPositive;
        if (index < foundIntegers.length)
            foundIntegers[index] = true;
    }

    for (int i = 0; i < foundIntegers.length; i++) {
        if (!foundIntegers[i])
            return i + smallestPositive;
    }
    return foundIntegers.length + smallestPositive;
}

Context

StackExchange Code Review Q#43818, answer score: 10

Revisions (0)

No revisions yet.