The O(n) Club: Russian Doll Envelopes: Where Sorting Actually Makes You Look Smart

The O(n) Club: Russian Doll Envelopes—Where Sorting Actually Makes You Look Smart

⚡ TL;DR

Find the most envelopes that fit inside each other, Russian-doll style—size must strictly increase in both width and height. Most people go brute force and get O(n²) runtime migraines. The pros use a sort-and-LIS trick and slip out before anyone notices. Here’s the flavor of the wrong way:

// Don’t even think about copy-pasting
int maxChain = 1;
for (int i = 0; i < n; ++i)
  for (int j = 0; j < i; ++j)
    if (env[j].width < env[i].width && env[j].height < env[i].height)
      maxChain = Math.max(maxChain, dp[j] + 1);

🧠 How Devs Usually Mess This Up

So, you sorted by width. Great. But when widths tie, you sorted height ascending? Get ready for envelopes nesting like Russian matryoshka clones—wrong! Forget about that strictly greater thing? Now you’re letting identical envelopes morph into a single envelope hydra. And if you tackled this with only DP, you probably saw your runtime stats weep uncontrollably. Sorting details and edge cases: ignore at your own peril.

🔍 What’s Actually Going On

This isn’t just a 2D LIS problem—it’s the sneaky cousin that needs a sorting Jedi move. By sorting envelopes by width ascending but height descending (for ties), you make sure equal widths don’t chain up, letting you safely apply classical LIS—in just one dimension. It’s algorithmic origami: fold once, then let LIS do the pretty part.

🛠️ PseudoCode

  • Step 1: Sort envelopes
    // Width ascending; if equal, height descending
    Arrays.sort(envelopes, (a, b) -> {
        if (a[0] == b[0]) return b[1] - a[1];
        return a[0] - b[0];
    });
    

    Why height descending? Keeps envelopes of the same width from forming an illegal queue.

  • Step 2: Extract heights
    int[] heights = new int[envelopes.length];
    for (int i = 0; i < envelopes.length; ++i)
        heights[i] = envelopes[i][1];
    

    Heights now represent your nesting potential. Live your best LIS life.

  • Step 3: Run LIS on heights (Patience Sorting Style)
    // Find LIS (longest increasing sequence) of heights
    List
    <integer> piles = new ArrayList<>();
    for (int h : heights) {
        int idx = Collections.binarySearch(piles, h);
        if (idx < 0) idx = -(idx + 1);
        if (idx == piles.size()) piles.add(h);
        else piles.set(idx, h);
    }
    // piles.size() is your answer
    </integer>

    Less patience, more results. O(n log n) and interviewers will nod approvingly.

💻 The Code

import java.util.*;
 public class RussianDollEnvelopes {
    public int maxEnvelopes(int[][] envelopes) {
        if (envelopes == null || envelopes.length == 0) return 0;
        Arrays.sort(envelopes, (a, b) -> {
            if (a[0] == b[0]) return b[1] - a[1];
            return a[0] - b[0];
        });
        int[] heights = new int[envelopes.length];
        for (int i = 0; i < envelopes.length; ++i) {
            heights[i] = envelopes[i][1];
        }
        List
<integer> piles = new ArrayList<>();
        for (int h : heights) {
            int idx = Collections.binarySearch(piles, h);
            if (idx < 0) idx = -(idx + 1);
            if (idx == piles.size()) piles.add(h);
            else piles.set(idx, h);
        }
        return piles.size();
    }
}
</integer>

⚠️ Pitfalls, Traps & Runtime Smacks

  • Sorting heights ascending for ties? Enjoy demoing a wrong answer—you’ll get chains of same-width envelopes if you do!
  • Forgetting ‘strictly greater’? Your answer will balloon with illegitimate envelopes. Test cases will not be kind.
  • All identical envelopes? Your solution should return 1. Don’t overthink; just smile and return 1.
  • Time/Space Complexity: O(n log n) time (because LIS with binary search) and O(n) space. Your future self thanks you for not doing O(n²).

🧠 Interviewer Brain-Tattoo

“Sort with brains. LIS with style. Descending tie-breakers: because Russian dolls shouldn’t be twins.”

Previous Article

The O(n) Club: Minimum Cost Tree From Leaf Values — Monotonic Stack Style

Next Article

The O(n) Club: Maximum Profit in Job Scheduling: How Not to Overbook Your Calendar (or Lose Your Mind)