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;


    }

}

 

posted @ 2018-07-06 23:08  朋友圈  阅读(285)  评论(0编辑  收藏  举报