354. Russian Doll Envelopes 俄罗斯套娃

这个题目,很纠结。。。我不管咋优化都无法优化都无法过测试。提示超时。。。。

先把思路说一下把!。

第一排序,先按照高度排序,然后剩下的就是宽度了。

再按照leetcode300的算法,固定i后就从0到i-1 去找那个能让dp[j]+1 最大的序列。当然条件就是

dp[i][0] > dp[j][0] && dp[i][1] > dp[j][1] 这样俄罗斯套信封才能装进去。

找到后就再遍历下dp的数值,找最大的那个dp数值。就是答案了。

看上去不难。难的是优化。。。咋优化那。

觉得leetcode套路太多了。

优化的办法是用一个特别的数组---递增数组。

当要加入的元素大于递增数组最后一个元素的时候,直接push进去。

当要加入的元素小于递增数组最后一个元素的时候,找比他搭的元素里最小的那个替换。

为啥要替换那?就是为了给后来人腾地方。 

数越小,以后能接上的数就越多,答案就越长。

下面就是答案了。。。

代码里有个cmp排序。为啥要做这个那?

为了是让相同高度,但是宽度不相同的元素被过滤掉一些。这样就能只考虑第二个元素宽度了。

如果直接不考虑第一个元素高度,只考虑宽度。那下面的就被误认为可以套娃了。毕竟3 < 6.

比如{4, 3}, {4, 6}

如果按照倒序排序 {4,6}, {4,3}。 在维护递增队列的时候,3就会被插入到递增队列里替代比他打的数。为后人做贡献。

哎 算法题真难。也真的很绕。

class Solution {
      static  bool cmp(vector<int> a, vector<int> b){
        if(a[0] == b[0]){
            return a[1]>b[1];
        }
        else
            return a[0]<b[0];
        
    }
public:
int maxEnvelopes(vector<vector<int>>& envelopes) {
        int n = envelopes.size();
        
        sort(envelopes.begin(), envelopes.end(), cmp);
        
        vector<int> q;
        
        for(auto envelop: envelopes){
            if(q.empty() || envelop[1] > q.back())
                q.push_back(envelop[1]);
            else{
                auto it = lower_bound(q.begin(), q.end(), envelop[1]);
                *it = envelop[1];
            }
        }
        return q.size();
        
    }
};

方法二:

    #if 0
    int maxEnvelopes(vector<vector<int>>& envelopes) {

        //https://www.youtube.com/watch?v=B1d2wV6mfzA
        //看完guan神的代码觉得真的很漂亮。
        // 这道题目和leetcode 300 一样,都是LSI,最长上升子序列。
        // 我们把信封的width排序好以后,就生下了高度了。
        // 比如example 1,排序以后就是
        // [2, 3], [5,4] [6,4], [6,7]
        // 要找最后一个信封所能套的最多信封数目,就得从第一个信封开始看。
        // [2,3] 可以,因为2 < 6, 3 < 7
        // [5, 4] 可以,因为5 < 6, 4 <7
        // 6, 4 不可以,因为6 = 6
        //于是就有两个信封可以被风道[6,7]里。如果能计算出[2,3],[5,4] 套住的信封,就好做了。
        
        //那就用DP把,可以算出来之前[2,3]能套住的信封数
        //max number of evnelopes can russian doll
        int n = envelopes.size();
        vector<int> dp(n, 1);
        
        sort(envelopes.begin(), envelopes.end(), cmp);
        
        for(int i=1;i < n; i++){
            for(int j = 0; j < i;j++){
                if(envelopes[i][0] > envelopes[j][0] && envelopes[i][1] > envelopes[j][1])
                    dp[i] = max(dp[i], dp[j]+1);
            }
        }
        
        int ret = 0;
        for(int i = 0;i < n;i++){
            ret = max(ret, dp[i]);
        }
        
        return ret;
#endif

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值