zoukankan      html  css  js  c++  java
  • LeetCode502

    北邮的同学问了我优先队列的用法,引出了这道题。

    好吧,我也被有限队列先入为主了。

    贪心算法,并且没有后效性。

    按照一开始的思路做,并做了一点小优化,超时

    public static class Node{
    
            //一定要有这个标识,不然删除不知道删哪个
            //int index;
    
            //被选过了就是true,没选就是false
            boolean flag = false;
            int cap;
            int pro;
            public Node(int x,int y){
                cap = x;
                pro = y;
            }
    
    
        }
    
        public int findMaximizedCapital(int k, int W, int[] Profits, int[] Capital) {
    
            //怎么通过每个启动资金,找到对应的利润呢?不解决这个问题,就无法对C进行排序,不然会找不到对应的P
            //Map不行,因为可能会有相同启动资金,但是利润不同的
            //自定义一个类即可!自定义数据结构真的是厉害。
    
            //构建一个Node的数组
    
            List<Node> list = new ArrayList<>();
    
            for(int i=0;i<Capital.length;i++){
                Node node = new Node(Capital[i],Profits[i]);
                list.add(node);
            }
    
            //通过C对list进行降序排序
            Collections.sort(list, new Comparator<Node>() {
                @Override
                public int compare(Node o1, Node o2) {
    
                    if(o1.cap>o2.cap)
                        return -1;
                    if(o1.cap<o2.cap)
                        return 1;
                    return 0;
                }
            });
    
            //每次遍历list,找到小于或等于W的第一个node,因为是降序,该node后面的都是比W小的
            //在比W小的所有node里面,找到P最大的那个
            for(int i=0;i<k;i++){
    
                PriorityQueue<Node> priorityQueue = new PriorityQueue<>(new Comparator<Node>() {
                    @Override
                    public int compare(Node o1, Node o2) {
                        if(o1.pro>o2.pro)
                            return -1;
                        if(o1.pro<o2.pro)
                            return 1;
                        return 0;
                    }
                });
                for(int j=0;j<list.size();j++){
                    Node node = list.get(j);
                    if(W>=node.cap&&!node.flag){
                        priorityQueue.add(node);
                    }
                }
    
                //对后续的都放入优先队列里,就能找到里面的最大值了
                Node node = priorityQueue.poll();
                //没有适合W的项目了
                if(node==null)
                    return W;
                W+=node.pro;
                node.flag=true;
    
                //删掉该项目
                //不需要这样删,想到了一个常数级优化
    //            Iterator<Node> iterator = list.iterator();
    //            while (iterator.hasNext()){
    //                Node temp = iterator.next();
    //                if(temp.index==node.index){
    //                    iterator.remove();
    //                    break;
    //                }
    //            }
    
            }
    
            return W;
    
    
        }

    好像不用每次都维护一个新的优先队列

    因为W肯定是递增的,那么只要把新元素加进优先队列就好了

    这算一个n*logn的优化吧!

    还有之前没有在循环中对list.size()进行优化

    两个优化下来果然过了

        public static class Node{
    
            //一定要有这个标识,不然删除不知道删哪个
            //int index;
    
            //被选过了就是true,没选就是false
            boolean flag = false;
            int cap;
            int pro;
            public Node(int x,int y){
                cap = x;
                pro = y;
            }
    
    
        }
    
        public int findMaximizedCapital(int k, int W, int[] Profits, int[] Capital) {
    
            //怎么通过每个启动资金,找到对应的利润呢?不解决这个问题,就无法对C进行排序,不然会找不到对应的P
            //Map不行,因为可能会有相同启动资金,但是利润不同的
            //自定义一个类即可!自定义数据结构真的是厉害。
    
            //构建一个Node的数组
    
            List<Node> list = new ArrayList<>();
    
            for(int i=0;i<Capital.length;i++){
                Node node = new Node(Capital[i],Profits[i]);
                list.add(node);
            }
    
            //通过C对list进行降序排序
            Collections.sort(list, new Comparator<Node>() {
                @Override
                public int compare(Node o1, Node o2) {
    
                    if(o1.cap>o2.cap)
                        return -1;
                    if(o1.cap<o2.cap)
                        return 1;
                    return 0;
                }
            });
    
            //每次遍历list,找到小于或等于W的第一个node,因为是降序,该node后面的都是比W小的
            //在比W小的所有node里面,找到P最大的那个
            //好像不用每次都维护一个新的优先队列
            //因为W肯定是递增的,那么只要把新元素加进优先队列就好了
            int len = list.size();
    
            //指向末尾
            int last = len-1;
            PriorityQueue<Node> priorityQueue = new PriorityQueue<>(new Comparator<Node>() {
                @Override
                public int compare(Node o1, Node o2) {
                    if(o1.pro>o2.pro)
                        return -1;
                    if(o1.pro<o2.pro)
                        return 1;
                    return 0;
                }
            });
            for(int i=0;i<k;i++){
    
                int j = 0;
                for(;j<len;j++){
                    Node node = list.get(j);
                    if(W>=node.cap){
                        break;
                    }
                }
    
                //把j~last之间的值,放到优先队列里!
                for(int q=j;q<=last;q++){
                    Node node = list.get(q);
                    if(!node.flag)
                        priorityQueue.add(node);
                }
    
                //更新last
                //如果last=j,那么j就多放了一次了
                last=j-1;
    
                //对后续的都放入优先队列里,就能找到里面的最大值了
                Node node = priorityQueue.poll();
                //没有适合W的项目了
                if(node==null)
                    return W;
                W+=node.pro;
                node.flag=true;
    
                //删掉该项目
                //不需要这样删,想到了一个常数级优化
    //            Iterator<Node> iterator = list.iterator();
    //            while (iterator.hasNext()){
    //                Node temp = iterator.next();
    //                if(temp.index==node.index){
    //                    iterator.remove();
    //                    break;
    //                }
    //            }
    
            }
    
            return W;
    
    
        }

    果然通过只是运气好。。。。

    想法----->实现------->提交,确定方法是否正确-------->优化

    每个都是大槛呢

    改成lambda的优雅写法

    public class LeetCode502 {
    
        //项目类
        public static class Node{
            //被选过了就是true,没选就是false
            boolean flag = false;
            int cap;
            int pro;
            public Node(int x,int y){
                cap = x;
                pro = y;
            }
        }
    
        public int findMaximizedCapital(int k, int W, int[] Profits, int[] Capital) {
    
    
            //构建一个Node的数组
            List<Node> list = new ArrayList<>();
    
            for(int i=0;i<Capital.length;i++){
                Node node = new Node(Capital[i],Profits[i]);
                list.add(node);
            }
    
            //通过C对list进行降序排序
            Collections.sort(list, (o1,o2)->{
                if(o1.cap>o2.cap)
                    return -1;
                if(o1.cap<o2.cap)
                    return 1;
                return 0;
            });
    
            //每次遍历list,找到小于或等于W的第一个node(j),因为是降序,该node后面的都是比W小的
            //在比W小的所有node里面,找到P最大的那个,方法就是把这些node都扔到优先队列里
            //因为每次W是递增的,所以下一次的j会比上一次靠前,所以每次循环只要把新增的项目加进优先队列即可
            int len = list.size();
    
    
            //指向末尾
            int last = len-1;
    
            //lambda表达式也可以,好像简便易行
            PriorityQueue<Node> priorityQueue = new PriorityQueue<>((o1,o2)->{
                    if(o1.pro>o2.pro)
                        return -1;
                    if(o1.pro<o2.pro)
                        return 1;
                    return 0;
            });
    
    
            //要选k个项目
            for(int i=0;i<k;i++){
    
                int j = 0;
                for(;j<len;j++){
                    Node node = list.get(j);
                    if(W>=node.cap){
                        break;
                    }
                }
    
                //把j~last之间的值,放到优先队列里!
                for(int q=j;q<=last;q++){
                    Node node = list.get(q);
                    if(!node.flag)
                        priorityQueue.add(node);
                }
    
                //更新last
                //如果last=j,那么j就多放了一次了
                last=j-1;
    
                //对后续的都放入优先队列里,就能找到里面的最大值了
                Node node = priorityQueue.poll();
                //没有适合W的项目了
                if(node==null)
                    return W;
    
                //有就把利润加到W里
                W+=node.pro;
                //标出该项目已经被选过
                node.flag=true;
    
            }
    
            return W;
    
    
        }
    
    }
  • 相关阅读:
    第三章:WebDriver 通过 XPath来 定位 table 表格
    第三章:对话框的 alertconfirmprompt 的处理
    第三章:iframe 的处理
    第三章:鼠标悬停 Actions
    第三章:文件上传
    弱网测试:Network-Emulator-Toolkit 工具中的一些词汇
    linux 下查看机器是cpu是几核的
    linux系统硬件配置
    Linux内核分析课程总结
    《Linux内核设计与实现》课本第四章自学笔记——20135203齐岳
  • 原文地址:https://www.cnblogs.com/weizhibin1996/p/9275863.html
Copyright © 2011-2022 走看看