354. Russian Doll Envelopes

    You have a number of envelopes with widths and heights given as a pair of integers (w, h). One envelope can fit into another if and only if both the width and height of one envelope is greater than the width and height of the other envelope.

    What is the maximum number of envelopes can you Russian doll? (put one inside other)

Example:

Input: [[5,4],[6,4],[6,7],[2,3]]
Output: 3 
Explanation: The maximum number of envelopes you can Russian doll is 3 ([2,3] => [5,4] => [6,7]).

Note:
​ Rotation is not allowed.


动态规划的方式,时间复杂度是O(n),首先调用头文件algorithm中的sort函数,按照pair.first为主,pair.second为辅从小到大排序。因为每个envelope本身就是一个信封,所以dp中的元素都初始化为1,遍历envelops,找到坐标为i的元素之前所有的可以被装进envelops[i]中的信封envelops[j],查看envelops[i]中最多可以装下多少个信封dp[j],找到最大的dp[j],那么坐标为i的信封最多装下max(dp[j]) + 1个信封(包括自己)。比较所有的信封能装下的最多的数量,最终得到结果。时间复杂度为O(n * n)

int maxEnvelopes(vector<pair<int, int>>& envelopes)
{
    sort(envelopes.begin(), envelopes.end());
    int maxlength = 0;
    vector<int> dp(envelopes.size(), 1);
    for(int i = 0; i < envelopes.size(); i++)
    {
        for(int j = 0; j < i; j++)
            if(envelopes[i].first > envelopes[j].first && envelopes[i].second > envelopes[j].second)dp[i] = dp[i] > (dp[j] + 1) ? dp[i] : (dp[j] + 1);
        maxlength = maxlength > dp[i] ? maxlength : dp[i];
    }
    return maxlength;

}

下面是另一种解法,排序的方式是pair.first小的排在前面,如果pair.first相同,则pair.second大的排在前面。

并且维护一个数组LIS,但是这个数组并不代表最长递增信封。遍历envelops,如果LIS的大小为0,那么直接将当前元素的second推入LIS,否则的话,利用lower_bound找到当前元素在LIS中应该插入的位置it,如果当前元素的second大于LIS 的最大值,那么将其推入LIS中,否则将it位置处的元素替换为second。最终得到的结构是LIS的大小。时间复杂度为O(n)

  1. 如果envelopes中没有出现first相同的状况,暂时假设排好序后,后面的信封总能将前面的信封装下,那么显然最终的结果是envelopes.size()。在下面的代码中,则是每遇见一个新元素,都会将这个新元素的second 装进LIS中。

  2. 如果envelopes中没有出现first相同的状况,但是出现了后一个的second小于前面的某一个信封的second的状况,那么在遇到这种元素之前,遇到的每一个信封的second都被装进了LIS中,当前能得到的最大嵌套数就是LISsize(),然后就碰到了上面所说的那种元素,这种元素的second因为小于前面某个信封的second,所以这个元素无法将前面所有的信封都装进自己里面,利用lower_bound找到当前元素的secondLIS中应该插入的位置it, 因为遍历数组的顺序是从小到大,所以可以肯定it之前的元素的widthheight肯定没有当前元素的width以及height 大,也就是说当前元素可以把it之前所有的元素都装进自己里面。但是当前能得到的嵌套数仍是LISsize()。此时LIS并不是一个嵌套序列,而从0到it的元素们是一个嵌套序列。

  3. 如果如果envelopes中出现了first相同的状况,那么按照上面所说的那种排序方式,如果first相同,second越大,排名越在前,这是因为在代码中往LIS中添加元素或者更改元素的时候没有关心first的大小,所以如果出现了例如[3,3], [6,5], [6,6]这样的状况,那么最终得到的结果会是3,这显然是不正确的。所以如果两个信封的first相同,就先用second较大的信封去装,这样就能保证second较小的信封不会把second较大的元素也装进来。
bool mycomp(pair<int, int>& l, pair<int, int>& r)
{
    return (l.first != r.first) ? (l.first < r.first) : (l.second > r.second);
}
int maxEnvelopes(vector<pair<int, int>>& envelopes)
{
    sort(envelopes.begin(), envelopes.end(), mycomp);
    vector<int> LIS;
    for(int i = 0; i < envelopes.size(); i++)
    {
        if(LIS.size() == 0)
        {
            LIS.push_back(envelopes[i].second);
            continue;
        }
        vector<int>::iterator it = lower_bound(LIS.begin(), LIS.end(), envelopes[i].second);
        if(it == LIS.end())LIS.push_back(envelopes[i].second);
        else (*it) = envelopes[i].second;
    }
    return LIS.size();
}

www.sunshangyu.top

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值