zoukankan      html  css  js  c++  java
  • 0354. Russian Doll Envelopes (H)

    Russian Doll Envelopes (H)

    题目

    You are given a 2D array of integers envelopes where envelopes[i] = [wi, hi] represents the width and the height of an envelope.

    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.

    Return the maximum number of envelopes can you Russian doll (i.e., put one inside the other).

    Note: You cannot rotate an envelope.

    Example 1:

    Input: envelopes = [[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]).
    

    Example 2:

    Input: envelopes = [[1,1],[1,1],[1,1]]
    Output: 1
    

    Constraints:

    • 1 <= envelopes.length <= 5000
    • envelopes[i].length == 2
    • 1 <= wi, hi <= 10^4

    题意

    给定n个信封,每个信封有高度和宽度,如果一个信封a的高度宽度都小于另一个信封b的高度宽度,则可以进行套娃操作,将a塞入b,问最多可以进行几次套娃操作。

    思路

    本质上就是LIS问题。对数组按照宽从小到大排序,如果相同则按照高从大到小排序(关键!),保证数组中后一个信封的宽都比前一个大,且当相邻信封的宽相等时,前一个信封的高一定比后一个信封的大(用于排除等宽信封不能套娃的特殊情况),这样就可以对每个信封的高组成的序列做一次最长递增子序列问题求解来得到答案。


    代码实现

    Java

    动态规划

    class Solution {
        public int maxEnvelopes(int[][] envelopes) {
            int ans = 1;
            int[] dp = new int[envelopes.length];
    
            Arrays.sort(envelopes, (a, b) -> a[0] != b[0] ? a[0] - b[0] : b[1] - a[1]);
            dp[0] = 1;
            for (int i = 1; i < dp.length; i++) {
                for (int j = 0; j < i; j++) {
                    dp[i] = Math.max(dp[i], envelopes[i][1] > envelopes[j][1] ? dp[j] + 1 : 1);
                }
                ans = Math.max(ans, dp[i]);
            }
    
            return ans;
        }
    }
    

    动态规划二分优化

    class Solution {
        public int maxEnvelopes(int[][] envelopes) {
            List<Integer> list = new ArrayList<>();
    
            // 关键:当宽度相同时,按照高度递减排序
            Arrays.sort(envelopes, (a, b) -> a[0] != b[0] ? a[0] - b[0] : b[1] - a[1]);
          
            for (int i = 0; i < envelopes.length; i++) {
                int pos = findPos(list, envelopes[i][1]);
                if (pos == list.size()) {
                    list.add(envelopes[i][1]);
                } else {
                    list.set(pos, envelopes[i][1]);
                }
            }
    
            return list.size();
        }
    
        private int findPos(List<Integer> list, int target) {
            int left = 0, right = list.size() - 1;
            while (left <= right) {
                int mid = (right - left) / 2 + left;
                if (list.get(mid) < target) {
                    left = mid + 1;
                } else if (list.get(mid) > target) {
                    right = mid - 1;
                } else {
                    return mid;
                }
            }
            return left;
        }
    }
    
  • 相关阅读:
    电脑开机慢是查看与解决方案
    做男人真难
    强大的数据恢复软件--EasyRecovery专业版
    30招让你从头到脚都健康
    教您如何使用SQL中的SELECT LIKE like语句
    SQL server经典电子书、工具和视频教程汇总
    数据开发-经典
    C# 数据操作工具类
    关于web请求中 获取真实IP
    生成二维码
  • 原文地址:https://www.cnblogs.com/mapoos/p/14598414.html
Copyright © 2011-2022 走看看