{x}
blog image

Russian Doll Envelopes

You are given a 2D array of integers envelopes where envelopes[i] = [wi, hi] represents the width and the height of an envelope.

One envelope can fit into another if and only if both the width and height of one envelope are greater than the other envelope's width and height.

Return the maximum number of envelopes you can Russian doll (i.e., put one inside the other).

Note: You cannot rotate an envelope.

 

Example 1:

Input: envelopes = [[5,4],[6,4],[6,7],[2,3]]
Output: 3
Explanation: The maximum number of envelopes you can Russian doll is 3 ([2,3] => [5,4] => [6,7]).

Example 2:

Input: envelopes = [[1,1],[1,1],[1,1]]
Output: 1

 

Constraints:

  • 1 <= envelopes.length <= 105
  • envelopes[i].length == 2
  • 1 <= wi, hi <= 105

Solution Explanation for Russian Doll Envelopes

This problem asks to find the maximum number of envelopes that can be nested within each other (Russian doll style), given a list of envelopes with width and height. An envelope A can fit inside envelope B if and only if A's width and height are both less than B's width and height.

The optimal solution uses a combination of sorting and a dynamic programming technique similar to finding the longest increasing subsequence.

1. Sorting:

The crucial first step is sorting the envelopes. We sort them primarily by width in ascending order. If two envelopes have the same width, we sort them by height in descending order. This is vital because we want to avoid situations where two envelopes have the same width, but one could fit inside the other, leading to an incorrect count.

2. Longest Increasing Subsequence (LIS):

After sorting, the problem transforms into finding the length of the longest increasing subsequence of the heights. Consider only the heights of the envelopes after the sorting step. Because of the sorting, an envelope i can be added to the LIS if its height is greater than the height of the last envelope in the current LIS.

We use dynamic programming to efficiently find the LIS. Specifically, we use a variation of the algorithm for this purpose that finds the length of the LIS while storing only the last element in each potential LIS. Let's illustrate:

  • d: an array to store the last height of the current LIS of each length (initially containing only the height of the first envelope).
  • Iteration: For each envelope's height h:
    • If h is greater than the largest height in d, append h to d, extending the LIS.
    • Otherwise, find the smallest height in d that is greater than or equal to h using binary search. This position idx represents the place where h can replace a height and potentially lead to a longer LIS.

3. Time and Space Complexity:

  • Time Complexity: O(N log N), dominated by the sorting step. The binary search within the loop takes O(log N) for each element, resulting in a total time complexity of O(N log N).
  • Space Complexity: O(N) in the worst case to store the d array.

Code Explanation (Python):

class Solution:
    def maxEnvelopes(self, envelopes: List[List[int]]) -> int:
        envelopes.sort(key=lambda x: (x[0], -x[1])) # Sort by width (asc), then height (desc)
        d = [envelopes[0][1]]  # Initialize d with the height of the first envelope
        for _, h in envelopes[1:]: # Iterate through heights
            if h > d[-1]:  # If h is greater than the last element in d, extend the LIS
                d.append(h)
            else: # Otherwise, find the smallest element in d >= h using binary search
                idx = bisect_left(d, h)
                d[idx] = h # Replace with h for potentially longer LIS
        return len(d) # Length of d is the length of the LIS, which is the answer

The other languages (Java, C++, Go) follow a very similar approach, employing the same sorting strategy and a modified binary search within the dynamic programming loop. The key differences are mainly syntactic variations specific to each language and subtle differences in how the binary search is implemented. The core algorithm remains consistent across all implementations.