一刷264-二分模块-354. 俄罗斯套娃信封问题(h)

题目:
给你一个二维整数数组 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.length <= 105
envelopes[i].length == 2
1 <= wi, hi <= 105
------------------------
思路:数组 + 排序 + 二分
一维升序,保证了后出现的一维一定大,后出现的信封如果二维大,
一定装得下先出现的信封。(一维不等的情况)

二维降序,保证一维相同的信封在后续出现的时候,不会影响第一条规则后续出现的,
二维大的信封,装得下前面出现的二维小的信封

综上,通过一个排序,保证了两件事儿,
一维升序,对于一维不同的数据来讲,二维最长递增子序列个数就是答案,
二维降序,对于相同的一维数据来讲,不破坏二维最长递增子序列个数就是答案这件事,

因为二维降序,一维相同二维小的信封都排在后边,
即如果二维小,要么是一维一样二维小,要么是一维较大但是二维较小,哪个都装不下。
整个问题变成了中等问题。求数组最长递增子序列问题。
----------------------
class Solution {
    public int maxEnvelopes(int[][] envelopes) {
        Arrays.sort(envelopes, (a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]);//排序
        int[] height = new int[envelopes.length];//存储二维元素: 高度
        int count = 0;//结果集:计算最终一共有多少个信封满足条件
        for (int i = 0; i < envelopes.length; i++) {//遍历
            int curHeight = envelopes[i][1];//获得数组的 二维元素: 高度
            if (count == 0 || curHeight > height[count - 1]) {//比较二维元素: 大的直接计数
                height[count++] = curHeight;
            }else {
                int left = 0;
                int right = count - 1;
                int res = 0;
                while (left <= right) {
                    int mid = left + ((right - left) >> 1);
                    if (height[mid] >= curHeight) {
                        res = mid;
                        right = mid - 1;
                    }else {
                        left = mid + 1;
                    }
                }
                height[res] = curHeight;
            }
        }
        return count;
    }
}
/**
Arrays.sort(envelopes, (a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]);
if(a[0]==b[0]){按第一维元素比较二维数组 
    return b[1]-a[1]; 若一维元素相同,则 二维元素 按 从大到小 降序
}else{//一维元素不相同, 则一维元素按从小到大 升序
       return a[0]-b[0];
}
 */

LC

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值