算法日常训练11.30(895.最大频率栈)
困难题,设计数据结构的,写的很少,直接看答案,发现看的懂,就直接看别人的答案学,这个答案是比较简单的,因为用了很多写好的数据结构,我们要做的就是对这些数据结构熟练掌握。
面向答案解释,优先队列用于实现栈的功能,自己自定义比较器,让他实现按频率弹出数据是比较简单的,但是如果有频率相同的数据,那么就要判断谁离栈顶更近,所以这里用index保存离栈顶的位置,还需要一个map来保存数据的次数,因为优先队列不能直接取出某一个数据来,那我们就不知道数据的次数,所以需要一个map保存,优先队列弹出以后map也要更新。
class FreqStack { private int index;//判定哪个离栈顶更近 private Map<Integer,Integer> map;//保存数据出现的次数 private PriorityQueue<int[]> queue;//模拟栈 public FreqStack() {//初始化 queue=new PriorityQueue<>(new Comparator<int[]>(){//自定义比较器 public int compare(int[] o1,int[] o2){ if(o1[1]==o2[1]){//出现次数相同,判断哪个离栈顶进 return o2[2]-o1[2]; } return o2[1]-o1[1];//不然就是判断哪个是最大频率数字 } }); map=new HashMap<>(); index=0; } public void push(int val) { int cnt=map.getOrDefault(val,0)+1;//次数 map.put(val,cnt); queue.add(new int[]{val,cnt,index++}); } public int pop() { int[] poll=queue.poll(); map.put(poll[0],poll[1]-1);//更新次数 return poll[0]; } } /** * Your FreqStack object will be instantiated and called as such: * FreqStack obj = new FreqStack(); * obj.push(val); * int param_2 = obj.pop(); */
差点就搞出来了,用的优先队列,但我想的是把通过率最低的班级排列,每次把最低的通过率的拿出来插一个学生进去,结果发现不能这样插,就以为自己优先队列这个想法是不通的,结果一看评论区发现一个几乎一样的答案,直接比增量就好了,不过也是踩着线过的,本来加了个输出数组的语句就超时了。
class Solution { public double maxAverageRatio(int[][] classes, int extraStudents) { PriorityQueue<int[]> queue=new PriorityQueue<>(new Comparator<int[]>() { @Override public int compare(int[] o1, int[] o2) { double avg1 = (o1[0] + 0.0) / o1[1]; double avg2 = (o2[0] + 0.0) / o2[1]; double avg1_add = (o1[0] + 1.0) / (o1[1] + 1.0); double avg2_add = (o2[0] + 1.0) / (o2[1] + 1.0); double res = Double.compare(avg1_add - avg1, avg2_add - avg2); if (res > 0) { return -1; } else { return 1; } } }); Collections.addAll(queue,classes); while(extraStudents>0){ int[] arr=queue.poll(); queue.offer(new int[]{arr[0]+1,arr[1]+1}); extraStudents--; } double res=0; while(!queue.isEmpty()){ int[] arr=queue.poll(); res+=((double)arr[0]/arr[1]); } return res/classes.length; } }
下一篇:
碌碌无为的一年研究生生活