[LeetCode] Russian Doll Envelopes 俄罗斯娃娃信封

Given an unsorted array of integers, find the length of longest increasing subsequence.

For example,
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.

Your algorithm should run in O(n2) complexity.

Follow up: Could you improve it to O(n log n) time complexity?

Credits:
Special thanks to @pbrother for adding this problem and creating all test cases.

这道题给了我们一堆大小不一的信封,让我们像套俄罗斯娃娃那样把这些信封都给套起来,这道题实际上是之前那道Longest Increasing Subsequence的具体应用,而且难度增加了,从一维变成了两维,但是万变不离其宗,解法还是一样的,首先来看DP的解法,这是一种brute force的解法,首先要给所有的信封按从小到大排序,首先根据宽度从小到大排,如果宽度相同,那么高度小的再前面,这是STL里面sort的默认排法,所以我们不用写其他的comparator,直接排就可以了,然后我们开始遍历,对于每一个信封,我们都遍历其前面所有的信封,如果当前信封的长和宽都比前面那个信封的大,那么我们更新dp数组,通过dp[i] = max(dp[i], dp[j] + 1)。然后我们每遍历完一个信封,都更新一下结果res,参见代码如下;

解法一:

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

我们还可以使用二分查找法来优化速度,我们首先要做的还是给信封排序,但是这次排序和上面有些不同,信封的宽度还是从小到大排,但是宽度相等时,我们让高度大的在前面。那么现在问题就简化了成了找高度数字中的LIS,完全就和之前那道Longest Increasing Subsequence一样了,所以我们还是使用之前那题解法来做,参见代码如下:

解法二:

class Solution {
public:
    int maxEnvelopes(vector<pair<int, int>>& envelopes) {
        vector<int> dp;
        sort(envelopes.begin(), envelopes.end(), [](const pair<int, int> &a, const pair<int, int> &b){
            if (a.first == b.first) return a.second > b.second;
            return a.first < b.first;
        });
        for (int i = 0; i < envelopes.size(); ++i) {
            int left = 0, right = dp.size(), t= envelopes[i].second;
            while (left < right) {
                int mid = left + (right - left) / 2;
                if (dp[mid] < t) left = mid + 1;
                else right = mid;
            }
            if (right >= dp.size()) dp.push_back(t);
            else dp[right] = t;
        }
        return dp.size();
    }
};

既然可以用二分查找法,那么使用STL的自带函数lower_bound也没啥问题了,参见代码如下:

解法三:

class Solution {
public:
    int maxEnvelopes(vector<pair<int, int>>& envelopes) {
        vector<int> dp;
        sort(envelopes.begin(), envelopes.end(), [](const pair<int, int> &a, const pair<int, int> &b){
            if (a.first == b.first) return a.second > b.second;
            return a.first < b.first;
        });
        for (int i = 0; i < envelopes.size(); ++i) {
            auto it = lower_bound(dp.begin(), dp.end(), envelopes[i].second);
            if (it == dp.end()) dp.push_back(envelopes[i].second);
            else *it = envelopes[i].second;
        }
        return dp.size();
    }
};

类似题目:

Longest Increasing Subsequence

参考资料:

https://leetcode.com/discuss/106836/simple-dp-solution

https://leetcode.com/discuss/106838/c-dp-version-time-o-n-2-space-o-n

https://leetcode.com/discuss/106888/java-answer-n-lg-n-time-using-binary-search

LeetCode All in One 题目讲解汇总(持续更新中...)

时间: 2024-10-10 06:24:20

[LeetCode] Russian Doll Envelopes 俄罗斯娃娃信封的相关文章

LeetCode &quot;Russian Doll Envelopes&quot;

An intuitive DP - should be 'medium'. class Solution { public: int maxEnvelopes(vector<pair<int, int>>& envelopes) { int n = envelopes.size(); if (!n) return 0; if (n == 1) return 1; // Sort by Area sort(envelopes.begin(), envelopes.end(),

leetCode 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

【leetcode】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. Wh

【Leetcode】Russian Doll Envelopes

题目链接:https://leetcode.com/problems/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 gr

动态规划——Russian Doll Envelopes

这个题大意很好理解,通过例子就能明白,很像俄罗斯套娃,大的娃娃套小的娃娃.这个题是大信封套小信封,每个信封都有长和宽,如果A信封的长和宽都要比B信封的要大,那么A信封可以套B信封,现在给定一组信封的大小,要求输出最多有几个信封能套在一起. Example:Given envelopes = [[5,4],[6,4],[6,7],[2,3]], the maximum number of envelopes you can Russian doll is 3 ([2,3] => [5,4] =>

[email&#160;protected] [354] Russian Doll Envelopes (Dynamic Programming)

https://leetcode.com/problems/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 tha

第十二周 Leetcode 354. Russian Doll Envelopes(HARD) LIS问题

Leetcode354 暴力的方法是显而易见的 O(n^2)构造一个DAG找最长链即可. 也有办法优化到O(nlogn) 注意 信封的方向是不能转换的. 对第一维从小到大排序,第一维相同第二维从大到小排序. 维护一个符合题意的队列,当队列中的第二维均比当前信封的第二维小时,必然可以增加到队尾. 如果不然,可以让当前信封作为"替补",它可以在恰当的时候代替恰好比它大的信封. 当替补们足够替换所有已有信封时,就可以增加新的信封了. 比较抽象,不过这个技巧很有趣. 看代码吧,很清晰. cla

[动态规划] leetcode 354 Russian Doll Envelopes

problem:https://leetcode.com/problems/russian-doll-envelopes/ 最长连续子序列类型问题.先排序,dp[i]记录使用第i个套娃的最大数量. bool cmp(const vector<int>& x, const vector<int>& y) { return x[0] == y[0] ? x[1] < y[1] : x[0] < y[0]; } class Solution { public:

354. Russian Doll Envelopes

从我花时间上看,我是纠结排序很久.注意一下Comparator的写法,以后会了就好~ 算法上讲,就是对envolope尺寸排序,然后对于排序后的每个信封,它可以装进的最多小信封数,是长宽都比它小的信封中装的进最多数目+1.和之前做的368. Largest Divisible Subset思路是一样的,甚至还要简单一点. 动规. 1 static class MySort implements Comparator<int[]> { 2 public int compare(int[] o1,