354. 俄罗斯套娃信封问题

首先,假设你已经做过300. 最长上升子序列,并能推导二分查找法及其正确性。

信封宽高为(w, h),当你w从小到大排列时,你可能觉得,该问题变成了最长上升子序列,只要高度一直增高,并找到最长的套娃层数即可。
但是有一个例外,就是你找到的上升序列,尽管高度递增,但可能会出现宽度相等的情况。
比如对于信封(1, 2) (1, 3),按照w排列,并找最长上升子序列后,得出答案是2。
为了避免这个情况,将信封宽度从小到大,同时高度从大到小排列。(比如(1,2)(1,3)(2,5)会排列成(1,3)(1,2)(2,5),这样能保证找到高度递增的子序列时,该子序列的宽度一定是不相等的。

我的答案:

class Solution:
    def maxEnvelopes(self, envelopes) -> int:
        envelopes.sort(key=lambda x: (x[0], -x[1]))  # 按照宽度递增,高度递减排序
        print(envelopes)

        dp = []
        # 接下来等同LIS
        for i, en in enumerate(envelopes):
            l, r = 0, len(dp) - 1
            pivot = len(dp)
            while l <= r:
                mid = (l+r) // 2
                if en[1] <= dp[mid]:
                    pivot = min(pivot, mid)
                    r = mid-1
                else:
                    l = mid+1
            if pivot == len(dp):
                dp.append(en[1])
            else:
                dp[pivot] = en[1]
            print(dp)
        return len(dp)

顺便一提,官方题解中用了lower_bound的思路来做,比较简洁。

由于二分查找问题容易出错,我阅读了youtube上五点七边的视频,并改写如下。改写后清爽多了:

class Solution:
    def maxEnvelopes(self, envelopes: List[List[int]]) -> int:
        envelopes.sort(key=lambda x: (x[0], -x[1]))

        dp = []
        for i, en in enumerate(envelopes):
            l, r = -1, len(dp)
            while l != r-1:
                m = (l+r) // 2
                if en[1] <= dp[m]:
                    r = m
                else:
                    l = m
            if r == len(dp):
                dp.append(en[1])
            else:
                dp[r] = en[1]
        return len(dp)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值