From bc8030b45a7e2a6cdefe8944cb624d4fa1f7d1a1 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sun, 28 Aug 2022 14:31:18 +0800 Subject: [PATCH] =?UTF-8?q?Update=200347.=E5=89=8DK=E4=B8=AA=E9=AB=98?= =?UTF-8?q?=E9=A2=91=E5=85=83=E7=B4=A0.md=EF=BC=8C=E6=96=B0=E5=A2=9ECompar?= =?UTF-8?q?ator=E6=8E=A5=E5=8F=A3=E8=AF=B4=E6=98=8E=E5=8F=8A=E5=A4=A7?= =?UTF-8?q?=E9=A1=B6=E5=A0=86=E3=80=81=E5=B0=8F=E9=A1=B6=E5=A0=86=E4=B8=A4?= =?UTF-8?q?=E7=A7=8Djava=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0347.前K个高频元素.md | 59 +++++++++++++++++++++------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/problems/0347.前K个高频元素.md b/problems/0347.前K个高频元素.md index d4059b9b..8256e629 100644 --- a/problems/0347.前K个高频元素.md +++ b/problems/0347.前K个高频元素.md @@ -140,24 +140,55 @@ public: Java: ```java +/*Comparator接口说明: + * 返回负数,形参中第一个参数排在前面;返回正数,形参中第二个参数排在前面 + * 对于队列:排在前面意味着往队头靠 + * 对于堆(使用PriorityQueue实现):从队头到队尾按从小到大排就是最小堆(小顶堆), + * 从队头到队尾按从大到小排就是最大堆(大顶堆)--->队头元素相当于堆的根节点 + * */ class Solution { - public int[] topKFrequent(int[] nums, int k) { - int[] result = new int[k]; - HashMap map = new HashMap<>(); - for (int num : nums) { - map.put(num, map.getOrDefault(num, 0) + 1); + //解法1:基于大顶堆实现 + public int[] topKFrequent1(int[] nums, int k) { + Map map = new HashMap<>();//key为数组元素值,val为对应出现次数 + for(int num:nums){ + map.put(num,map.getOrDefault(num,0)+1); } - - Set> entries = map.entrySet(); - // 根据map的value值,构建于一个大顶堆(o1 - o2: 小顶堆, o2 - o1 : 大顶堆) - PriorityQueue> queue = new PriorityQueue<>((o1, o2) -> o2.getValue() - o1.getValue()); - for (Map.Entry entry : entries) { - queue.offer(entry); + //在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数 + //出现次数按从队头到队尾的顺序是从大到小排,出现次数最多的在队头(相当于大顶堆) + PriorityQueue pq = new PriorityQueue<>((pair1, pair2)->pair2[1]-pair1[1]); + for(Map.Entry entry:map.entrySet()){//大顶堆需要对所有元素进行排序 + pq.add(new int[]{entry.getKey(),entry.getValue()}); } - for (int i = k - 1; i >= 0; i--) { - result[i] = queue.poll().getKey(); + int[] ans = new int[k]; + for(int i=0;i map = new HashMap<>();//key为数组元素值,val为对应出现次数 + for(int num:nums){ + map.put(num,map.getOrDefault(num,0)+1); + } + //在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数 + //出现次数按从队头到队尾的顺序是从小到大排,出现次数最低的在队头(相当于小顶堆) + PriorityQueue pq = new PriorityQueue<>((pair1,pair2)->pair1[1]-pair2[1]); + for(Map.Entry entry:map.entrySet()){//小顶堆只需要维持k个元素有序 + if(pq.size()pq.peek()[1]){//当前元素出现次数大于小顶堆的根结点(这k个元素中出现次数最少的那个) + pq.poll();//弹出队头(小顶堆的根结点),即把堆里出现次数最少的那个删除,留下的就是出现次数多的了 + pq.add(new int[]{entry.getKey(),entry.getValue()}); + } + } + } + int[] ans = new int[k]; + for(int i=k-1;i>=0;i--){//依次弹出小顶堆,先弹出的是堆的根,出现次数少,后面弹出的出现次数多 + ans[i] = pq.poll()[0]; + } + return ans; } } ```