当前位置:   article > 正文

代码随想录Day13_priorityqueue pq = new priorityqueue<>((pai

priorityqueue pq = new priorityqueue<>((pair1, pair2)->pair2[1]-pair1
239. 滑动窗口最大值

题有点难,先代码码下来慢慢看

  1. //解法一
  2. //自定义数组
  3. class MyQueue {
  4. Deque<Integer> deque = new LinkedList<>();
  5. //弹出元素时,比较当前要弹出的数值是否等于队列出口的数值,如果相等则弹出
  6. //同时判断队列当前是否为空
  7. void poll(int val) {
  8. if (!deque.isEmpty() && val == deque.peek()) {
  9. deque.poll();
  10. }
  11. }
  12. //添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出
  13. //保证队列元素单调递减
  14. //比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2
  15. void add(int val) {
  16. while (!deque.isEmpty() && val > deque.getLast()) {
  17. deque.removeLast();
  18. }
  19. deque.add(val);
  20. }
  21. //队列队顶元素始终为最大值
  22. int peek() {
  23. return deque.peek();
  24. }
  25. }
  26. class Solution {
  27. public int[] maxSlidingWindow(int[] nums, int k) {
  28. if (nums.length == 1) {
  29. return nums;
  30. }
  31. int len = nums.length - k + 1;
  32. //存放结果元素的数组
  33. int[] res = new int[len];
  34. int num = 0;
  35. //自定义队列
  36. MyQueue myQueue = new MyQueue();
  37. //先将前k的元素放入队列
  38. for (int i = 0; i < k; i++) {
  39. myQueue.add(nums[i]);
  40. }
  41. res[num++] = myQueue.peek();
  42. for (int i = k; i < nums.length; i++) {
  43. //滑动窗口移除最前面的元素,移除是判断该元素是否放入队列
  44. myQueue.poll(nums[i - k]);
  45. //滑动窗口加入最后面的元素
  46. myQueue.add(nums[i]);
  47. //记录对应的最大值
  48. res[num++] = myQueue.peek();
  49. }
  50. return res;
  51. }
  52. }
  1. //解法二
  2. //利用双端队列手动实现单调队列
  3. /**
  4. * 用一个单调队列来存储对应的下标,每当窗口滑动的时候,直接取队列的头部指针对应的值放入结果集即可
  5. * 单调队列类似 (tail -->) 3 --> 2 --> 1 --> 0 (--> head) (右边为头结点,元素存的是下标)
  6. */
  7. class Solution {
  8. public int[] maxSlidingWindow(int[] nums, int k) {
  9. ArrayDeque<Integer> deque = new ArrayDeque<>();
  10. int n = nums.length;
  11. int[] res = new int[n - k + 1];
  12. int idx = 0;
  13. for(int i = 0; i < n; i++) {
  14. // 根据题意,i为nums下标,是要在[i - k + 1, i] 中选到最大值,只需要保证两点
  15. // 1.队列头结点需要在[i - k + 1, i]范围内,不符合则要弹出
  16. while(!deque.isEmpty() && deque.peek() < i - k + 1){
  17. deque.poll();
  18. }
  19. // 2.既然是单调,就要保证每次放进去的数字要比末尾的都大,否则也弹出
  20. while(!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {
  21. deque.pollLast();
  22. }
  23. deque.offer(i);
  24. // 因为单调,当i增长到符合第一个k范围的时候,每滑动一步都将队列头节点放入结果就行了
  25. if(i >= k - 1){
  26. res[idx++] = nums[deque.peek()];
  27. }
  28. }
  29. return res;
  30. }
  31. }
347. 前 K 个高频元素
  1. /*Comparator接口说明:
  2. * 返回负数,形参中第一个参数排在前面;返回正数,形参中第二个参数排在前面
  3. * 对于队列:排在前面意味着往队头靠
  4. * 对于堆(使用PriorityQueue实现):从队头到队尾按从小到大排就是最小堆(小顶堆),
  5. * 从队头到队尾按从大到小排就是最大堆(大顶堆)--->队头元素相当于堆的根节点
  6. * */
  7. class Solution {
  8. //解法1:基于大顶堆实现
  9. public int[] topKFrequent1(int[] nums, int k) {
  10. Map<Integer,Integer> map = new HashMap<>();//key为数组元素值,val为对应出现次数
  11. for(int num:nums){
  12. map.put(num,map.getOrDefault(num,0)+1);
  13. }
  14. //在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数
  15. //出现次数按从队头到队尾的顺序是从大到小排,出现次数最多的在队头(相当于大顶堆)
  16. PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2)->pair2[1]-pair1[1]);
  17. for(Map.Entry<Integer,Integer> entry:map.entrySet()){//大顶堆需要对所有元素进行排序
  18. pq.add(new int[]{entry.getKey(),entry.getValue()});
  19. }
  20. int[] ans = new int[k];
  21. for(int i=0;i<k;i++){//依次从队头弹出k个,就是出现频率前k高的元素
  22. ans[i] = pq.poll()[0];
  23. }
  24. return ans;
  25. }
  26. //解法2:基于小顶堆实现
  27. public int[] topKFrequent2(int[] nums, int k) {
  28. Map<Integer,Integer> map = new HashMap<>();//key为数组元素值,val为对应出现次数
  29. for(int num:nums){
  30. map.put(num,map.getOrDefault(num,0)+1);
  31. }
  32. //在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数
  33. //出现次数按从队头到队尾的顺序是从小到大排,出现次数最低的在队头(相当于小顶堆)
  34. PriorityQueue<int[]> pq = new PriorityQueue<>((pair1,pair2)->pair1[1]-pair2[1]);
  35. for(Map.Entry<Integer,Integer> entry:map.entrySet()){//小顶堆只需要维持k个元素有序
  36. if(pq.size()<k){//小顶堆元素个数小于k个时直接加
  37. pq.add(new int[]{entry.getKey(),entry.getValue()});
  38. }else{
  39. if(entry.getValue()>pq.peek()[1]){//当前元素出现次数大于小顶堆的根结点(这k个元素中出现次数最少的那个)
  40. pq.poll();//弹出队头(小顶堆的根结点),即把堆里出现次数最少的那个删除,留下的就是出现次数多的了
  41. pq.add(new int[]{entry.getKey(),entry.getValue()});
  42. }
  43. }
  44. }
  45. int[] ans = new int[k];
  46. for(int i=k-1;i>=0;i--){//依次弹出小顶堆,先弹出的是堆的根,出现次数少,后面弹出的出现次数多
  47. ans[i] = pq.poll()[0];
  48. }
  49. return ans;
  50. }
  51. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/277105
推荐阅读
相关标签
  

闽ICP备14008679号