本篇推文共计2000个字,阅读时间约3分钟。
01
题目描述
题目描述:
给定一些标记了宽度和高度的信封,宽度和高度以整数对形式(w, h)出现。
当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里。
如同俄罗斯套娃一样。
说明:不允许旋转信封。
举例如下:
输入: envelopes = [ [5,4], [6,4], [6,7], [2,3], [7,8]]
输出: 4
最多信封的个数为4,
组合为: [2,3] => [5,4] => [6,7] =>[7,8]。
即
[2,3]放进[5,4]
[5,4]放进[6,7]
[6,7]放进[7,8]
一共可套4个信封
02
代码分析
由题目描述可知
可看为两个维度都递增的最长单调递增子序列问题
何为最长单调递增子序列问题?
给你一个整数数组nums,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。
举例如下:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],
因此长度为 4 。
单调递增子序列这个问题我们在这篇文章中有深入详细地解释,强烈推荐看完下面这篇文章后,
再来解决信封问题。
所以本题可以转化为两个维度都递增的最长单调递增子序列问题
已知envelopes =[[5,4], [6,4], [6,7], [2,3], [7,8]]
envelopes是一个多维数组
我们换一种多维数组表现形式
envelopes =
[[5,4],
[6,4],
[6,7],
[2,3],
[7,8]]
envelopes是一个5*2维数组
对于这样的数组,可以先对数组envelopes第1维数据升序,第2维数据降序,
从而减少代码对第1维数据的判断流程
[[5,4], [6,4], [6,7], [2,3], [7,8]]排序后变为了
[[2,3], [5,4], [6,7], [6,4], [7,8]]
代码表示为:
envelopes.sort(key=lambda x:(x[0],-x[1]))
#key=lambda x:(x[0],-x[1]))
#代码中x[0]表示数组envelopes的第一维数据,
#x[1]表示数组envelopes的第二维数据
这样此问题就转变为在一维整数数组nums,找到其中最长严格递增子序列的长度问题,还是强烈建议看完此篇后再来看信封问题的解决方案。
故我们接着分析:
设置一个数组dp[i]
该数组dp[i]的值代表多维数组envelopes前i个元素的最长递增子序列长度
,那么数组dp[]中的最大值即为信封问题答案
因为多维数组envelopes中每个元素都可单独组成一个信封,即至少一个信封可以组成一个“俄罗斯套娃”。
故将数组dp初始化为1
dp=[1]*N
N为envelopes长度
我们有以下分析:
设j∈[0,i),考虑每轮计算新dp[i]时,遍历 [0,i)列表区间,做以下判断:
1.当nums[i][1]>nums[j][1]时:
nums[i][1]可以接在nums[j][1]之后(此题要求严格递增),
此情况下最长上升子序列长度为
dp[i]=dp[j]+1;
2.当nums[i][1]<=nums[j][1]时:
nums[i]无法接在nums[j]之后,
此情况上升子序列不成立,
跳过
在情况1中,计算出dp[j]+1的最大值,
即为数组envelopes的最长上升子序列长度。
具体实现的办法可以使用遍历j时,
每轮执行最大值比较公式:
dp[i] = max(dp[i], dp[j] + 1)
将遍历每一轮的最长上升子序列长度存入dp[i]中
如下图所示:
对多维数组envelopes
第1维数据升序,第2维数据降序后
如下图所示:
当i=0时,此时多维数组
envelopes=[[2,3], [5,4], [6,7], [6,4], [7,8]]
只有[2,3]一个子元素,
也即是“一个信封”可以组成一个“俄罗斯套娃”
故此时dp=1,如下图所示:
当i=1时,此时多维数组
envelopes=[[2,3], [5,4], [6,7], [6,4], [7,8]]
有[2,3],[5,4]两个子元素,[2,3]可以放入[5,4]
也即是“2个信封”可以组成一个“俄罗斯套娃”
故此时dp=2,如下图紫色区域标出。
当i=2时,此时多维数组
envelopes=[[2,3], [5,4], [6,7], [6,4], [7,8]]
有[2,3], [5,4],[6,7],三个子元素,
[2,3]可以放入[5,4],[5,4]可以放入[6,7],
也即是“3个信封”可以组成一个“俄罗斯套娃”
故此时dp=3,如下图紫色区域标出。
当i=3时,此时多维数组
envelopes=[[2,3], [5,4], [6,7], [6,4], [7,8]]
有[2,3], [5,4],[6,7], [6,4]四个子元素,
[2,3]可以放入[5,4],[5,4]可以放入[6,7],
[6,7]放入不了[6,4]
也即是“3个信封”可以组成一个“俄罗斯套娃”
故此时dp=3,如下图紫色区域标出。
当i=4时,此时多维数组
envelopes=[[2,3], [5,4], [6,7], [6,4], [7,8]]
有[2,3], [5,4],[6,7], [6,4],[7,8]五个子元素,
[2,3]可以放入[5,4],[5,4]可以放入[6,7],
[6,7]放入不了[6,4],[6,7]可以放入[7,8]
也即是“4个信封”可以组成一个“俄罗斯套娃”
故此时dp=4,如下图紫色区域标出。
我们用代码表示为
class Solution:
def maxEnvelopes(self, envelopes: List[List[int]]) -> int:
if not envelopes:
return 0
N = len(envelopes)
envelopes.sort(key= lambda x:(x[0], -x[1]))
dp = [1] * N
for i in range(N):
for j in range(i):
if envelopes[j][1] < envelopes[i][1]:
dp[i] = max(dp[i], dp[j] + 1)
return max(dp)
往期回顾
☆ END ☆
你与世界
只差一个
公众号