【优选算法】优先级队列:最后一块石头的重量,数据流中的第K大元素,前K个高频单词,数据流中的中位数

文章目录

TOP - K问题主要有两种比较优秀的解法:

  • 堆 时间复杂度:O(n * log2n)
  • 快速选择算法 时间复杂度O(n) ,空间开销比较大

1. 最后一块石头的重量(LC1046)

最后一块石头的重量

题目描述

解题思路

利用大根堆模拟这个过程,每次取出前两个大的元素碰撞,得到的结果再入队.

代码实现

java 复制代码
class Solution {
    public int lastStoneWeight(int[] stones) {
        PriorityQueue<Integer> heap = new PriorityQueue<>((a,b)->b-a);
        //入队
        for (int stone : stones) 
            heap.offer(stone);
            
        while(heap.size()>1){
            int s1 = heap.poll();
            int s2 = heap.poll();
            if(s1!=s2)
                heap.offer(s1-s2);
        }
        return heap.isEmpty()?0:heap.poll();
    }
}

2. 数据流中的第K大元素(LC703)

数据流中的第K大元素

题目描述

解题思路

  1. 创建大小为K的小根堆
  2. 循环,元素依次进堆,判断堆的大小是否超过k,如果超过则令堆顶元素出堆。

代码实现

java 复制代码
class KthLargest {
    int k;
    int[] nums;
    PriorityQueue<Integer> heap = new PriorityQueue<>();
    public KthLargest(int k, int[] nums) {
        this.k = k;
        this.nums = nums;
        for(int x:nums){
            heap.offer(x);
            if(heap.size()>k)
                heap.poll();
        }
    }
    
    public int add(int val) {
        heap.offer(val);
        if(heap.size()>k)
            heap.poll();
        return heap.peek();
    }
}

3. 前K个高频单词(LC692)

前K个高频单词

题目描述

解题思路

利用堆来解决。

  1. 利用哈希表统计单词对应的次数
  2. 创建大小为k的堆
    • 对于频次,应该创建小根堆
    • 对于字典序(频次相同时),应该创建大根堆,让序列靠后的单词先出堆。
  3. 循环,让元素依次进堆,判断
  4. 提取结果,小根堆依次提取的结果是从小到大的,可以逆序存放在结果数组中,也可以调用reverse方法

代码实现

java 复制代码
class Solution {
    public List<String> topKFrequent(String[] words, int k) {
        List<String> ret = new ArrayList<>();
        HashMap<String,Integer> hash = new HashMap<>();
        //预处理,统计频次
        for(String word:words){
            if(hash.containsKey(word))
                hash.put(word,hash.get(word)+1);
            else
                hash.put(word,1);
        }

        //创建小根堆
        PriorityQueue<Map.Entry<String,Integer>> heap = new PriorityQueue<>((o1,o2) ->{
            if(o1.getValue().equals(o2.getValue()))
                    return o2.getKey().compareTo(o1.getKey());
                else
                    return o1.getValue() - o2.getValue();
        });

        //循环入队
        for(Map.Entry<String,Integer> entry:hash.entrySet()){
            heap.offer(entry);
            if(heap.size()>k)
                heap.poll();
        }

        //提取结果
        while(!heap.isEmpty())
            ret.add(heap.poll().getKey());
        
        Collections.reverse(ret);
        return ret;
    }
}

4. 数据流中的中位数(LC295)

数据流中的中位数

题目描述

解题思路

  • 利用大小堆来解决,创建大根堆存放左半边的元素,数量为m,小根堆存放右半边的元素,数量为n,保持m==n或m==n+1 。m==n时,分别取两个堆的堆顶元素,求平均值;m==n+1 时,取大根堆的堆顶元素就是中位数。
  • addNum : 分类讨论,要保证m==n或m==n+1
    • m==n时,取大根堆堆顶元素x
      • num<x 或 大根堆为空时,x添加到大根堆
      • 否则 添加到小根堆中,但是此时右边比左边数量多,取出堆顶元素y,放入小根堆中
    • m==n+1
      • num>x,直接放入右边
      • 否则先把x放入左边,x出堆放入右边。

代码实现

java 复制代码
class MedianFinder {
    PriorityQueue<Integer> left = new PriorityQueue<>((a,b)->b-a);
    PriorityQueue<Integer> right = new PriorityQueue<>();

    public MedianFinder() {
        
    }
     
    public void addNum(int num) {
        
        if(left.size()==right.size()){
            if(left.isEmpty() || left.peek()>=num)
                left.offer(num);
            else{
                right.offer(num);
                left.offer(right.poll());
            }
        }else{
            if(left.peek()<=num)
                right.offer(num);
            else{
                left.offer(num);
                right.offer(left.poll());
            }
        }
    }
    
    public double findMedian() {
        if(left.size()>right.size())
            return left.peek();
        else
            return (left.peek()+right.peek())/2.0 ;
    }
}
相关推荐
Logic1015 小时前
C语言/数据结构位运算题解:异或XOR找出学习计划中的“独特学习时间“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
小蒋学算法6 小时前
算法-交替删除操作后最后剩下的整数-跟着灵茶山艾府学算法
数据结构·算法
荆棘鸟智能6 小时前
林业遥感长势评估怎么做?从NDVI时序分析到LiDAR蓄积量回归
人工智能·算法·智慧林业
hhb_6187 小时前
AIRAGDebug:一键定位RAG链路异常
人工智能·python·算法
朝朝辞暮i7 小时前
C++ 第 6 课:switch —— 多状态选择
开发语言·c++·算法
苏打豆8 小时前
Pinocchio源码阅读——刚体运动物理量空间变换及求导
c++·线性代数·算法·矩阵·机器人
FluxArt8 小时前
GPT Image 2.5 中文提示词教程:Flux Art 可复用模板
前端·gpt·算法
思麟呀8 小时前
位运算:从一个整数到一个集合
c语言·数据结构·c++·算法
阜阳山君GEO9 小时前
豆包 SEED 新版本 GEO 优化:信源金字塔、打分体系与避坑落地指南
人工智能·算法
晓天衡宇•评测社区9 小时前
晓天衡宇亮相 2026 云栖大会:迈向更可信的高质量评测
人工智能·算法·机器学习