算法奇妙屋(十二)-优先级队列(堆)

文章目录

一. 力扣 1046. 最后一块石头的重量

1. 题目

2. 算法原理

这道题的算法原理十分简单, 直接建立大根堆即可, 这里简单梳理下

3. 代码

java 复制代码
    public int lastStoneWeight(int[] stones) {
        PriorityQueue<Integer> queue = new PriorityQueue<>((a,b) -> b - a);
        for (int x : stones) {
            queue.offer(x);
        }
        while (queue.size() > 1) {
            int max1 = queue.poll();
            int max2 = queue.poll();
            if (max1 > max2) {
                queue.offer(max1 - max2);
            }
        }
        if (!queue.isEmpty()) {
            return queue.poll();
        }else {
            return 0;
        }
    }

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

1. 题目

题目意思简单易懂, 这里不过多赘述, 直接看图即可

2. 算法原理

这道题有点绕口, 这里我们在初始化类的时候先求出来topk, 然后在后台调用add方法的时候, 只需要重复求topk流程即可, 下面图片解析的是求topk问题时,应该建立哪种类型的堆, 为什么要建这种堆?

3. 代码

java 复制代码
    PriorityQueue<Integer> q;
    int t_k;

    public KthLargest(int k, int[] nums) {
        q = new PriorityQueue<>();
        t_k = k;
        for (int x : nums) {
            q.offer(x);
            if (q.size() > t_k) {
                q.poll();
            }
        }
    }

    public int add(int val) {
        q.offer(val);
        if (q.size() > t_k) {
            q.poll();
        }
        return q.peek();
    }

三. 力扣 692. 前K个高频单词

1. 题目

2. 算法原理

这道题原理不难, 难的是如何将代码实现, 注意掌握Pair的特性

3. 代码

java 复制代码
    public List<String> topKFrequent(String[] words, int k) {
        Map<String, Integer> hash = new HashMap<>();
        for (String s : words) {
            hash.put(s, hash.getOrDefault(s, 0) + 1);
        }
        PriorityQueue<Pair<String, Integer>> q = new PriorityQueue<>(
                (a, b) -> {
                    if (a.getValue().equals(b.getValue())) {
                        return b.getKey().compareTo(a.getKey());
                    }else {
                        return a.getValue() - b.getValue();
                    }
                }
        );
        for (Map.Entry<String, Integer> e : hash.entrySet()) {
            q.offer(new Pair<>(e.getKey(), e.getValue()));
            if (q.size() > k) {
                q.poll();
            }
        }
        List<String> ret = new ArrayList<>();
        while (!q.isEmpty()) {
            ret.add(q.poll().getKey());
        }
        Collections.reverse(ret);
        return ret;
    }

四. 力扣 295. 数据流的中位数

1. 题目

题目就是让求中位数, 最后结果需要注意是double类型

2. 算法原理

(1) 我们这里采用大小堆的解法, 下面我们来解释什么是大小堆

(2)一些细节问题, 例如如何入堆?如何维护顺序排列的数据流?

3. 代码

java 复制代码
    PriorityQueue<Integer> left;
    PriorityQueue<Integer> right;

    public MedianFinder() {
        left = new PriorityQueue<>((a, b) -> b - a);
        right = new PriorityQueue<>();
    }

    public void addNum(int num) {
        int m = left.size();
        int n = right.size();
        Integer x = left.peek();
        if (m == n) {
            if (x == null) {
                left.offer(num);
            } else if (num <= x) {
                left.offer(num);
            } else {
                right.offer(num);
                left.offer(right.poll());
            }
        } else {
            if (num <= x) {
                left.offer(num);
                x = left.poll();
                right.offer(x);
            }else {
                right.offer(num);
            }
        }

    }

    public double findMedian() {
        if (left.size() == right.size()) {
            return (left.peek() + right.peek()) / 2.0;
        }else {
            return left.peek();
        }
    }
相关推荐
踩坑记录21 分钟前
leetcode hot100 寻找两个正序数组的中位数 hard 二分查找 双指针
leetcode
旖-旎24 分钟前
深搜练习(电话号码字母组合)(3)
c++·算法·力扣·深度优先遍历
谭欣辰26 分钟前
C++快速幂完整实战讲解
算法·决策树·机器学习
Mr_pyx31 分钟前
【LeetHOT100】随机链表的复制——Java多解法详解
算法·深度优先
AIFarmer1 小时前
【无标题】
开发语言·c++·算法
AGV算法笔记1 小时前
CVPR 2025 最新感知算法解读:GaussianLSS 如何用 Gaussian Splatting 重构 BEV 表示?
算法·重构·自动驾驶·3d视觉·感知算法·多视角视觉
勤劳的进取家2 小时前
数据链路层基础
网络·学习·算法
Advancer-2 小时前
第二次蓝桥杯总结(上)
java·算法·职场和发展·蓝桥杯
ん贤3 小时前
加密算法(对称、非对称、哈希、签名...)
算法·哈希算法
superior tigre3 小时前
78 子集
算法·leetcode·深度优先·回溯