0354 Russian Doll Envelope#
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
Dynamic programming
Patience sort
def maxEnvelopes(envelopes):
# O(N2) cannot pass due to time limit
n = len(envelopes)
# dp table
dp = [1]*n
# sort the envelopes in ascending order
envelopes.sort(key=lambda x: (x[0], -x[1]))
# fill dp
for i in range(1, n):
for j in range(i):
if envelopes[i][0] > envelopes[j][0] and envelopes[i][1] > envelopes[j][1]:
dp[i] = max(dp[i], dp[j]+1)
return max(dp)
# test
envelopes = [[5,4],[6,4],[6,7],[2,3]]
print(maxEnvelopes(envelopes))
envelopes = [[1,1],[1,1],[1,1]]
print(maxEnvelopes(envelopes))
envelopes = [[1,1],[2,2],[3,3],[4,4],[5,5]]
print(maxEnvelopes(envelopes))
envelopes = [[1,1],[2,2],[3,3],[4,4],[5,5],[5,6],[6,7],[7,8],[8,9],[9,10]]
print(maxEnvelopes(envelopes))
# add a length 0f 10000 test case
envelopes = [[i, i] for i in range(10000)]
print(maxEnvelopes(envelopes))
3
1
5
9
10000
def maxEnvelopes(envelopes):
# O(nlogn) solution
# sort the envelopes in ascending order of width, and descending order of height
# then find the longest increasing subsequence of heights
# the time complexity is O(nlogn) + O(nlogn) = O(nlogn)
# the space complexity is O(n)
n = len(envelopes)
# sort the envelopes
envelopes.sort(key=lambda x: (x[0], -x[1]))
# find the longest increasing subsequence of heights
heights = [envelope[1] for envelope in envelopes]
dp = []
dp.append(heights[0])
for i in range(1, n):
num = heights[i]
# if num is greater than the last element in dp, append it to dp
if num > dp[-1]:
dp.append(num)
# if num is smaller than the last element in dp, find the first element in dp that is greater than num using binary search
else:
l, r = 0, len(dp)-1
while l < r:
mid = l + (r-l)//2
# if the mid element is smaller than num, search the right half
if dp[mid] < num:
l = mid +1
elif dp[mid] > num:
r = mid
else:
# if the mid element is equal to num, search the left half because we want to find the first element that is no less than than num
r = mid
dp[l] = num
return len(dp)
# test
envelopes = [[5,4],[6,4],[6,7],[2,3]]
print(maxEnvelopes(envelopes))
envelopes = [[1,1],[1,1],[1,1]]
print(maxEnvelopes(envelopes))
envelopes = [[1,1],[2,2],[3,3],[4,4],[5,5]]
print(maxEnvelopes(envelopes))
envelopes = [[1,1],[2,2],[3,3],[4,4],[5,5],[5,6],[6,7],[7,8],[8,9],[9,10]]
print(maxEnvelopes(envelopes))
# add a length 0f 10000 test case
envelopes = [[i, i] for i in range(10000)]
print(maxEnvelopes(envelopes))
3
1
5
9
10000