俄罗斯套娃信封问题

原题指路

俄罗斯套娃信封问题

题目描述

给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。

请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。

说明:
不允许旋转信封。

解题思路

图片1.png
困难题就直接参考一波官方题解……

  1. 首先,在套娃前进行准备工作,对信封按照第一维 w w w进行升序排列,先得到一个 w w w的递增序列;
  2. 其次,为了防止后面迭代过程中出错,即保证当信封的 w w w相等时,仅会在一个序列里选中其中一个信封,所以将信封的第二维 h h h作为次关键字将序列按降序排列(与第1步合并为以 w w w为主关键字,以 h h h为次关键字的快排);
  3. 在排序完成后,就可以开始套娃(bushi)动态规划了,用 d p [ i ] dp[i] dp[i]表示当序列长度为 i i i时最外面一层信封的 h h h
  4. 动态规划的步骤具体可以用二分实现(易证迭代过程中dp为严格单调递增序列):
    1. 若当前信封的 h i > d p [ − 1 ] h_{i} > dp[-1] hi>dp[1]时,则 d p [ l e n ( d p ) + 1 ] = h i dp[len(dp)+1]=h_{i} dp[len(dp)+1]=hi
    2. 否则就二分求出 i n d e x index index使 d p [ i n d e x ] ≤ h i < d p [ i n d e x + 1 ] dp[index] \le h_{i} < dp[index+1] dp[index]hi<dp[index+1],且使 d p [ i n d e x ] = h i dp[index] = h_{i} dp[index]=hi
  5. 最后返回 l e n ( d p ) len(dp) len(dp)即可。

时间复杂度: O ( n log ⁡ n ) O(n\log{n}) O(nlogn)(注:快排和基于二分的动态规划均为 O ( n log ⁡ n ) O(n\log{n}) O(nlogn)
空间复杂度: O ( n ) O(n) O(n)

代码

class Solution:

    def maxEnvelopes(self, envelopes: List[List[int]]) -> int:
        if not envelopes:  # 空列表直接返回
            return 0

        length = len(envelopes)
        envelopes.sort(key=lambda x: (x[0], -x[1]))  # 按第一维升序,第二位降序对信封进行快排
        dp = [envelopes[0][1]]
        for i in range(1, length):
            if (num := envelopes[i][1]) > dp[-1]:
                dp.append(num)
            else:  # 二分查找部分
                index = bisect.bisect_left(dp, num)
                dp[index] = num
        return len(dp)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值