【一天一道Leetcode】套信封问题

本篇推文共计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 。

单调递增子序列这个问题我们在这篇文章中有深入详细地解释,强烈推荐看完下面这篇文章后,

 

【一天一道Leetcode】最长递增子序列长度

再来解决信封问题。

所以本题可以转化为两个维度都递增的最长单调递增子序列问题

已知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,找到其中最长严格递增子序列的长度问题,还是强烈建议看完此篇后再来看信封问题的解决方案。

【一天一道Leetcode】最长递增子序列长度

故我们接着分析:

设置一个数组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)

往期回顾

【年终总结】你好2021,再见2020。


【快速写好毕业论文】你不得不知晓的七个常用文献搜索平台

【秋招纪实录】一篇特别正经的【腾讯】求职经验分享

【一天一道Leetcode】矩阵不可变

【一天一道Leetcode】比特位计数

【一天一道Leetcode】数组不可变

☆ END ☆

你与世界

只差一个

公众号

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值