Welcome to Subscribe On Youtube

Question

Formatted question description: https://leetcode.ca/all/354.html

 354	Russian Doll Envelopes

 You have a number of envelopes with widths and heights given as a pair of integers (w, h).

 One envelope can fit into another if and only if:
    both the width and height of one envelope is greater than the width and height of the other envelope.

 What is the maximum number of envelopes can you Russian doll? (put one inside other)

 Note:
 Rotation is not allowed.

 Example:

 Input: [[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]).

 @tag-dp

Algorithm

Consider a situation [100,100],[200,200], [1,300],[2,400],[3,500]. If you only update x in p(x,y) every time, then the next three will be thrown away, and the maximum value is 2, while correct reulst should be 3.

First, we must sort all the envelopes from smallest to largest.

  • First row according to the width from small to large,
  • If the width is the same, then the height is smaller and then the front,

Then we start to traverse, for each envelope, we traverse all the envelopes before it,

  • If the length and width of the current envelope are larger than those of the previous envelope, then we update the dp array by dp[i] = max(dp[i], dp[j] + 1).
  • Then every time we traverse an envelope, we update the result

Follow up of this question

If the envelope can be rotated. What is the longest sequence?

The answer is to enqueue <3,4>, then <4,3> also enqueue, and then find the longest sequence.

Code

Java

  • import java.util.Arrays;
    
    public class Russian_Doll_Envelopes {
    
    
    
        /*
            要考虑一种情况 [100,100],[200,200], [1,300],[2,400],[3,500]
            如果只是每次更新p(x,y)中的x,那么后面三个就会都被扔掉,最大值是2
         */
        class Solution {
    
            public int maxEnvelopes(int[][] envelopes) {
    
                if (envelopes == null || envelopes.length == 0) {
                    return 0;
                }
    
                int[] dp = new int[envelopes.length]; // at index=i, longest count
                int maxLen = 1;
    
                Arrays.sort(envelopes, (a,b)-> a[0] == b[0]? a[1] - b[1] : a[0] - b[0]);
    
                for (int right = 0; right < envelopes.length; right++) {
    
                    dp[right] = 1;
    
                    for (int left = 0; left < right; left++) {
    
                        if (envelopes[left][0] < envelopes[right][0] && envelopes[left][1] < envelopes[right][1]) {
                            dp[right] = Math.max(dp[right], dp[left] + 1);
                            maxLen = Math.max(maxLen, dp[right]);
                        }
    
                    }
                }
    
                return maxLen;
            }
        }
    }
    
  • // OJ: https://leetcode.com/problems/russian-doll-envelopes/
    // Time: O(NlogN)
    // Space: O(N)
    // Ref: https://leetcode.com/problems/russian-doll-envelopes/discuss/82763/Java-NLogN-Solution-with-Explanation
    class Solution {
    public:
        int maxEnvelopes(vector<vector<int>>& A) {
            sort(begin(A), end(A), [](auto &a, auto &b) { return a[0] != b[0] ? a[0] < b[0] : a[1] > b[1]; });
            vector<int> dp;
            for (auto &v : A) {
                auto it = lower_bound(begin(dp), end(dp), v[1]);
                if (it == end(dp)) dp.push_back(v[1]);
                else *it = v[1];
            }
            return dp.size();
        }
    };
    
  • '''
    >>> envelopes = [[100,100],[200,200], [1,300],[2,400],[2,401], [2,402], [3,500]]
    >>> envelopes.sort(key=lambda key: (key[0], -key[1]))
    >>> envelopes
    [[1, 300], [2, 402], [2, 401], [2, 400], [3, 500], [100, 100], [200, 200]]
    >>>
    >>>
    >>> tails = []
    >>> bisect.bisect_right(tails, envelopes[0][1])
    0
    >>> tails.append(envelopes[0][1])
    >>>
    >>> bisect.bisect_right(tails, envelopes[1][1])
    1
    >>> tails.append(envelopes[1][1])
    >>> tails
    [300, 402]
    >>>
    >>> bisect.bisect_right(tails, envelopes[2][1]) # [2, 401]
    1
    '''
    
    # w increasing-ordered, if w ties then h decreasing ordered. then it's the question of Longest Increasing Subsequence for all h (As of LC-300 Longest Increasing Subsequence)
    
    class Solution(object):
      def maxEnvelopes(self, envelopes):
        """
        :type envelopes: List[List[int]]
        :rtype: int
        """
        # why -key[1], not key[1]?
        # so that when [[1, 300], [2, 402], [2, 401], [2, 400], [3, 500], [100, 100], [200, 200]], for w=2, we want to keep [2,400] not keep [2,402] to potentially have longer increasing subsequence
        envelopes.sort(key=lambda key: (key[0], -key[1]))
        tails = []
        for i in range(0, len(envelopes)):
          idx = bisect.bisect_right(tails, envelopes[i][1])
          if idx - 1 >= 0 and tails[idx - 1] == envelopes[i][1]:
            continue # avoid de-dup
          if idx == len(tails):
            tails.append(envelopes[i][1])
          else:
            tails[idx] = envelopes[i][1]
        return len(tails)
    
    ############
    
    class Solution:
        def maxEnvelopes(self, envelopes: List[List[int]]) -> int:
            envelopes.sort(key=lambda x: (x[0], -x[1]))
            d = [envelopes[0][1]]
            for _, h in envelopes[1:]:
                if h > d[-1]:
                    d.append(h)
                else:
                    idx = bisect_left(d, h)
                    if idx == len(d):
                        idx = 0
                    d[idx] = h
            return len(d)
    

All Problems

All Solutions