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 the maximum number of envelopes can you Russian doll? (put one inside other)

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] => [6,7]).

本题是一个俄罗斯套娃问题,给定了一系列的矩形,问最多有多少个可以嵌套在一起。看到题目的第一反应应该就是先把矩阵中的所有元素按照宽度进行排序,然后在进行逐一的比较,并使用一个数组来记录当前矩形能嵌套的最大矩形个数。如果下一个比这个大,就+1;代码如下所示:

    public int maxEnvelopes(int[][] envelopes) {
        //将矩阵按照第一个元素进行排序
        Arrays.sort(envelopes, (a, b) -> a[0] - b[0]);
        int max = 0;
        //记录每个矩形能嵌套的个数
        int dp [] = new int [envelopes.length];
        //遍历所有矩形
        for(int i = 0; i < envelopes.length; i++){
            dp[i] = 1;//最少是1,他自己
            //遍历其前面的所有矩形,如果能嵌套在自己里面,就将其值+1
            for(int j = 0; j < i; j++){
                if(envelopes[j][0] < envelopes[i][0] && envelopes[j][1] < envelopes[i][1])
                    dp[i] = Math.max(dp[i], dp[j] + 1);
            }
            //保存目前为止的最大记录;
            max = Math.max(dp[i], max);
        }
        return max;
    }

上面这短代码时间复杂度比较高,因为他对每个矩形都要遍历之前所有的矩形,只能击败15%的用户。有一种改进的方法就是,将矩阵按照宽度增序排列,宽度相同时在按照高度降序排列。这样我们就不需要在考虑宽度的问题,只需要考虑高度的数组,按照之前的longest increasing subsequence这道题目寻找高度列表中最大的增序数组长度即可。这样在排序之后我们只需要在寻找一个数组的最大增序列即可,代码效率极大提高,可以击败90%的用户。代码入下:

    public static int maxEnvelopes1(int[][] envelopes) {
        if(envelopes == null || envelopes.length == 0
                || envelopes[0] == null || envelopes[0].length != 2)
            return 0;
        Arrays.sort(envelopes, new Comparator<int[]>(){
            public int compare(int[] arr1, int[] arr2){
                if(arr1[0] == arr2[0])
                    return arr2[1] - arr1[1];
                else
                    return arr1[0] - arr2[0];
            }
        });
        int dp[] = new int[envelopes.length];
        int len = 0;
        for(int[] envelope : envelopes){
            int index = Arrays.binarySearch(dp, 0, len, envelope[1]);
            if(index < 0)
                index = -(index + 1);
            dp[index] = envelope[1];
            if(index == len)
                len++;
        }
        return len;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值