/* * @lc app=leetcode.cn id=354 lang=cpp * * [354] 俄罗斯套娃信封问题 * * https://leetcode-cn.com/problems/russian-doll-envelopes/description/ * * algorithms * Hard (43.72%) * Likes: 513 * Dislikes: 0 * Total Accepted: 56.1K * Total Submissions: 128.1K * Testcase Example: '[[5,4],[6,4],[6,7],[2,3]]' * * 给你一个二维整数数组 envelopes ,其中 envelopes[i] = [wi, hi] ,表示第 i 个信封的宽度和高度。 * * 当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。 * * 请计算 最多能有多少个 信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。 * * 注意:不允许旋转信封。 * * * 示例 1: * * * 输入:envelopes = [[5,4],[6,4],[6,7],[2,3]] * 输出:3 * 解释:最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。 * * 示例 2: * * * 输入:envelopes = [[1,1],[1,1],[1,1]] * 输出:1 * * * * * 提示: * * * 1 * envelopes[i].length == 2 * 1 i, hi * * */
思路:
先对宽度w
进行升序排序,如果遇到w
相同的情况,则按照高度h
降序排序。之后把所有的h
作为一个数组,在这个数组上计算 LIS(最长递增子序列) 的长度就是答案。
这是把二维的问题转换为一维的问题,好进行状态推导。
对w进行排序后,则只需要考虑h,但是对于w相等的情况,如果h还继续按照升序排序,那么对h进行处理时,会先将[w,h1]算进去,然后将[w,h2]算进去,但是w相同的两个信封无法嵌套。所以对于w相等的,h降序排序。这样在对h进行最长递增子序列计算时,先取到了h2,就不会再继续取h1了。
class Solution { public: int maxEnvelopes(vector<vector<int>>& envelopes) { int n=envelopes.size(); sort(envelopes.begin(),envelopes.end(), [](vector<int> a,vector<int>b){ if(a[0]!=b[0]) return a[0]<b[0]; return a[1]>b[1]; }); vector<int> t; for(int i=0;i<n;++i){ t.push_back(envelopes[i][1]); } int res=LIS(t); return res; } int LIS(vector<int> & t) { int n=t.size(); vector<int> top(n); int piles=0; for(int i=0;i<n;++i){ int left=0,right=piles; int poker=t[i]; while(left<right){ int mid=(left+right)/2; if(poker>top[mid]) left=mid+1; else right=mid; } if(left==piles) piles++; top[left]=poker; } return piles; } };