TopK问题

90 阅读1分钟

问题总览

微信图片_20230506101439.png

序号题目完成
215. 数组中的第K个最大元素
703. 数据流中的第K大元素
剑指 Offer 40. 最小的k个数
347. 前K个高频元素
692. 前K个高频单词
378. 有序矩阵中第K小的元素

题解

215. 数组中的第K个最大元素

在其他文章里有写过,可以参考:排序算法

703. 数据流中的第K大元素

class KthLargest {

    PriorityQueue<Integer> queue;
    int target;

    public KthLargest(int k, int[] nums) {
        target = k;
        queue = new PriorityQueue<>();
        for (int num : nums) {
            offer(num);
        }
    }

    public void offer(int val) {
        queue.offer(val);
        if (queue.size() > target) {
            queue.poll();
        }
    }

    public int add(int val) {
        offer(val);
        return queue.peek();
    }
}

347. 前K个高频元素

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        // 得到每一个元素的频率
        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            int count = map.getOrDefault(num, 0);
            map.put(num, count + 1);
        }

        // 利用小顶堆对频率进行排序,小顶堆里存放的就是频率前k高的元素
        PriorityQueue<Frequent> queue = new PriorityQueue<>((o1, o2) -> {
            return o1.frequent - o2.frequent;
        });

        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            queue.offer(new Frequent(entry.getKey(), entry.getValue()));
            if (queue.size() > k) {
                queue.poll();
            }
        }

        // 构造结果,因为结果是从大到小排列,而堆是从小到大,所以数组从后往前填入值
        int[] ans = new int[k];
        for (int i = k - 1; i >= 0; i--) {
            ans[i] = queue.poll().key;
        }
        return ans;
    }

    class Frequent {
        int key;
        int frequent;

        public Frequent(int key, int frequent) {
            this.key = key;
            this.frequent = frequent;
        }
    }
}
//leetcode submit region end(Prohibit modification and deletion)

剑指 Offer 40. 最小的k个数

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>((o1, o2) -> {
            return o2 - o1;
        });
        for (int i = 0; i < arr.length; i++) {
            priorityQueue.offer(arr[i]);
            if (priorityQueue.size() > k) {
                priorityQueue.poll();
            }
        }
        int[] res = new int[k];
        for (int i = 0; i < k; i++) {
            res[i] = priorityQueue.poll();
        }
        return res;
    }
}

378. 有序矩阵中第K小的元素

class Solution {
    public int kthSmallest(int[][] matrix, int k) {
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((o1, o2) -> {
            return o2 - o1;
        });
        for (int[] rows : matrix) {
            for (int num : rows) {
                priorityQueue.offer(num);
                if (priorityQueue.size() > k) {
                    priorityQueue.poll();
                }
            }
        }
        return priorityQueue.peek();
    }
}

692. 前K个高频单词

//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public List<String> topKFrequent(String[] words, int k) {
        // 先记录出现频率
        Map<String, Integer> map = new HashMap<>();
        for (String word : words) {
            map.put(word, map.getOrDefault(word, 0) + 1);
        }
        // 大的沉底,小的踢出
        PriorityQueue<Frequent> priorityQueue = new PriorityQueue<Frequent>((o1, o2) -> {
            if (o1.count == o2.count) {
                // 其次是字典序
                return o2.str.compareTo(o1.str);
            }
            // 优先是出现频次高的单词
            return o1.count - o2.count;
        });
        for (String str : map.keySet()) {
            priorityQueue.offer(new Frequent(str, map.get(str)));
            if (priorityQueue.size() > k) {
                priorityQueue.poll();
            }
        }
        LinkedList<String> ans = new LinkedList<>();
        for (int i = 0; i < k; i++) {
            ans.addFirst(priorityQueue.poll().str);
        }
        return ans;
    }

    public class Frequent {
        String str;
        int count;

        public Frequent(String str, int count) {
            this.str = str;
            this.count = count;
        }

    }
}
//leetcode submit region end(Prohibit modification and deletion)