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; } }