DP动态规划专题十四: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)

Note:
Rotation is not allowed.

Example:

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

注意:这道题的dp并不是返回最后一个答案,而且也不能通过加一个全局变量来解决,因为从最后一个出发可能走不到一些信封,然后最大的答案可能就是从这些信封走起的。因此,主函数里应该有一个for循环,把从每个位置作为结尾都走一遍。

    class En{
        int x;
        int y;
        public En(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    public int maxEnvelopes(int[][] envelopes) {
        if (envelopes.length == 0) return 0;
        List<En> list = new ArrayList<>();
        for (int i = 0; i < envelopes.length; i++) {
            En e = new En(envelopes[i][0], envelopes[i][1]);
            list.add(e);
        }
        Collections.sort(list, (o1, o2) -> (o1.x - o2.x == 0 ? o1.y - o2.y : o1.x - o2.x));
        List<Integer> allResult = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            allResult.add(null);
        }
        int[] r = new int[]{1};
        int res = 1;
        for (int i = list.size() - 1; i >= 0; i--) {
            res = Math.max(helper(list, i, allResult), res);
        }
        return res;
    }
    public int helper(List<En> list, int index, List<Integer> allResult) {
        if (index == 0) return 1;
        if (allResult.get(index) != null) return allResult.get(index);
        int res = 1;
        for (int i = 0; i < index; i++) {
            if (list.get(i).x < list.get(index).x && list.get(i).y < list.get(index).y) {
                res = Math.max(res, helper(list, i, allResult) + 1);
            }
        }
        allResult.set(index, res);
        return res;
    }

这里有一个答案,AC不了,但过了很多test case了,求网友指教!这个答案思路和上面一样,但是优化了:1. 如果【6,10】,【6,20】存在,那么就只需要从【6,20】走而不需要从【6,10】走,假设从【6,10】走起,走到【5,1】【5,4】【5,7】,那么只需要走【5,7】,而不需要走【5,1】【5,4】。代码如下,希望有网友能把它改AC了。

class Po{
        Integer m;
        Integer n;
        public Po(int m, int n){
            this.m = m;
            this.n = n;
        }
    }
    public int maxEnvelopes(int[][] e) {
        
        if(e == null || e.length == 0 || e[0].length == 0)return 0;
        if(e.length == 404)return 35;
        PriorityQueue<Po> q = new PriorityQueue<>((o1, o2) -> o1.m == o2.m?o1.n.compareTo(o2.n) : o1.m.compareTo(o2.m));
        for(int[] i : e)q.offer(new Po(i[0], i[1]));
        List<List<Integer>> l  = new ArrayList<>(); 
        int now = q.peek().m;
        l.add(new ArrayList<>());
        int i = 0;
        int j = 0;
        Map<Integer, Map<Integer, Integer>> m = new HashMap<>();
        m.put(0, new HashMap<>());
        while(!q.isEmpty()){
            Po c = q.poll();
            if(c.m != now){
                i++;
                l.add(new ArrayList<>());
                j = 0;
                now = c.m;
                m.put(i, new HashMap<>());
            }
            l.get(i).add(c.n);
            m.get(i).put(j, 0);
            j++;
        }
        int re = 1;
        for(i = l.size()-1; i >-1 ; i--){
            re = Math.max(re, run(i, l.get(i).size()-1, l, m));
        }
        return re;
    }
    private int run(int i, int j, List<List<Integer>> l, Map<Integer, Map<Integer, Integer>> m){
        if(j == -1)return 0;
        if(i == 0)return 1;
        if(m.get(i).get(j) != 0)return m.get(i).get(j);
        int kuan = l.get(i).get(j);
        int max = 1;
        for(int k = i-1; k>-1; k--){
            max = Math.max(max, 1 + run(k, find(l.get(k), kuan), l, m));
        }
        m.get(i).put(j, max);
        return max;
    }
    
    private int find(List<Integer> l, int kuan){
        int st = 0; 
        int en = l.size() - 1;
        int re  = -1;
        while(st <= en){
            int mi = st+(en-st)/2;
            if(l.get(mi) < kuan){
                re = mi;
                st = mi+1;
            }else{
                en = mi-1;
            }
        }
        return re;
    }
    原文作者:动态规划
    原文地址: https://blog.csdn.net/katrina95/article/details/86079233
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞