The O(n) Club: Kth Missing Positive Number, or Why Your Integers Keep Vanishing

The O(n) Club: Kth Missing Positive Number, or Why Your Integers Keep Vanishing

⚡ TL;DR

If you want the kth missing positive integer from a sorted array, you could count each one by hand—if you hate free time. Instead, peep the math and binary search:

// Pure brute force, best paired with a strong coffee:
int miss = 0, num = 1, i = 0;
while (miss < k) {
    if (i < arr.length && arr[i] == num) i++;
    else miss++;
    num++;
}
return num - 1; // Slow and steady loses the interview

🧠 How Devs Usually Mess This Up

Most folks think “Oh, I’ll just count from 1 upward, skipping anything in arr.” Then they run it for k = 9001 and wonder why the recruiter stopped responding. Even if you’re faster, someone forgets that off-by-one in arr[i] - (i + 1) and ends up returning candidate #42, not #41. Bonus: Hard-coding assumes arrays always start at 1—because, sure, the world’s that clean.

🔍 What’s Actually Going On

Picture a stadium seat chart with random missing chairs, and your boss yells, “Give me the 5th missing seat number, STAT!” At position i in arr, the number of gaps before is arr[i] - (i + 1). Want the kth missing? Don’t loop with a flashlight; use binary search to jump right to the gap’s doorstep. Edge cases: If you’re missing numbers before arr[0], don’t even need the array. And if you run off the end, just add what’s left to the last arr value. Lazy, but it works.

🛠️ PseudoCode

  • Step 1: If k is less than arr[0], congrats, kth missing is just k.
    if (k < arr[0]) return k;
  • Step 2: Binary search for smallest index l where missings ≥ k:
    int l = 0, r = arr.length - 1;
    while (l <= r) {
        int m = l + (r - l) / 2;
        int missing = arr[m] - (m + 1);
        if (missing < k) l = m + 1;
        else r = m - 1;
    }
  • Step 3: If l == arr.length, kth missing comes past arr’s end:
    return arr[arr.length - 1] + (k - (arr[arr.length - 1] - arr.length));
  • Step 4: Else, find kth missing before arr[l]:
    return arr[l - 1] + (k - (arr[l - 1] - l));

💻 The Code

public int findKthPositive(int[] arr, int k) {
    int n = arr.length;
    if (k < arr[0]) return k;
    int l = 0, r = n - 1;
    while (l <= r) {
        int m = l + (r - l) / 2;
        int miss = arr[m] - (m + 1);
        if (miss < k) l = m + 1;
        else r = m - 1;
    }
    if (l == n) {
        return arr[n - 1] + (k - (arr[n - 1] - n));
    }
    return arr[l - 1] + (k - (arr[l - 1] - l));
}

⚠️ Pitfalls, Traps & Runtime Smacks

  • Missing Before Start: If arr starts after 1, and k is tiny, don’t even read arr; kth is k. No, really.
  • Off-by-One Special: Forgetting one plus/minus and you’ll be off by an entire bug bounty.
  • Unsorted or Duplicates? Problem expects perfection. Feed it junk, get junk results.
  • Overshooting: If binary search runs off-the-right, just add leftovers to arr’s last. Like topping off your coffee with energy drink.
  • Performance: O(log n). Use brute force and lose your lunch break.

🧠 Interviewer Brain-Tattoo

“Gaps in your array don’t go away if you ignore them. But with math and binary search, at least you won’t waste a lifetime finding them.”

Previous Article

The O(n) Club: Sliding Window Median: The Interview See-Saw Nobody Warns You About

Next Article

The O(n) Club: Next Greater Node in a Linked List—Stack Sorcery, Java Edition