leetcode-hot100 堆

目录

Java 堆相关知识点

1. 堆的初始化

2. 堆的相关函数

3. 堆的原理

4. 运用堆进行排序

5. 怎么用优先队列实现大顶堆:

示例代码

自定义比较器实现大顶堆

总结

刷题:

 数组中的第K个最大元素

前K个高频元素 

数据流的中位数 


Java 堆相关知识点

1. 堆的初始化

在 Java 中,堆是一种数据结构,通常用于实现优先队列。堆可以通过 PriorityQueue 类来初始化。PriorityQueue 是一个基于优先级的无界队列,底层实现是一个数组,它默认按照自然顺序进行排序,也可以通过自定义比较器进行排序。

示例代码:

import java.util.PriorityQueue;

public class Main {
    public static void main(String[] args) {
        // 初始化一个堆
        PriorityQueue heap = new PriorityQueue<>();
        
        // 添加元素到堆中
        heap.add(3);
        heap.add(1);
        heap.add(2);
        
        // 输出堆的内容
        System.out.println(heap); // 输出: [1, 3, 2]
    }
}
2. 堆的相关函数

PriorityQueue 提供了一系列方法来操作堆:

  • add(E e):将指定元素插入堆中。

  • offer(E e):将指定元素插入堆中,与 add 类似,但不抛出异常。

  • remove():移除并返回堆顶元素(最小值)。

  • poll():移除并返回堆顶元素,与 remove 类似,但不抛出异常。

  • peek():返回但不移除堆顶元素。

  • size():返回堆中的元素数量。

  • clear():清空堆中的所有元素。

示例代码:

import java.util.PriorityQueue;

public class Main {
    public static void main(String[] args) {
        PriorityQueue heap = new PriorityQueue<>();
        heap.add(3);
        heap.add(1);
        heap.add(2);
        
        // 获取并移除堆顶元素
        System.out.println(heap.poll()); // 输出: 1
        System.out.println(heap.poll()); // 输出: 2
        System.out.println(heap.poll()); // 输出: 3
        
        // 检查堆是否为空
        System.out.println(heap.isEmpty()); // 输出: true
    }
}
3. 堆的原理

堆是一种特殊的树形数据结构,通常是一个完全二叉树。堆分为两种类型:最大堆和最小堆。在最小堆中,父节点的值总是小于或等于子节点的值;在最大堆中,父节点的值总是大于或等于子节点的值。

PriorityQueue 默认实现的是最小堆。堆的底层实现通常使用数组,通过索引计算父节点和子节点的位置:

  • 父节点索引:(index - 1) / 2

  • 左子节点索引:2 * index + 1

  • 右子节点索引:2 * index + 2

4. 运用堆进行排序

堆排序是一种利用堆数据结构进行排序的算法。堆排序的基本步骤如下:

  1. 构建堆:将数组构建成一个最大堆或最小堆。

  2. 排序:反复取出堆顶元素(最大值或最小值),并将剩余元素重新调整为堆。

示例代码:

java复制

import java.util.PriorityQueue;

public class Main {
    public static void main(String[] args) {
        int[] arr = {3, 1, 2, 5, 4};
        
        // 使用最小堆进行排序
        PriorityQueue heap = new PriorityQueue<>();
        for (int num : arr) {
            heap.add(num);
        }
        
        // 将元素按顺序取出,得到排序后的数组
        for (int i = 0; i < arr.length; i++) {
            arr[i] = heap.poll();
        }
        
        // 输出排序后的数组
        for (int num : arr) {
            System.out.print(num + " "); // 输出: 1 2 3 4 5
        }
    }
}
5. 怎么用优先队列实现大顶堆:

在 Java 中,PriorityQueue 类默认实现的是 小顶堆(最小堆)。这意味着堆顶元素(即队列的头部)是堆中最小的元素。

示例代码

java复制

import java.util.PriorityQueue;

public class Main {
    public static void main(String[] args) {
        PriorityQueue heap = new PriorityQueue<>();
        heap.add(3);
        heap.add(1);
        heap.add(2);

        // 输出堆顶元素(最小值)
        System.out.println(heap.peek()); // 输出: 1

        // 移除堆顶元素并输出
        System.out.println(heap.poll()); // 输出: 1
        System.out.println(heap.peek()); // 输出: 2
    }
}
自定义比较器实现大顶堆

如果需要实现大顶堆(最大堆),可以通过自定义比较器(Comparator)来实现:

java复制

import java.util.PriorityQueue;
import java.util.Comparator;

public class Main {
    public static void main(String[] args) {
        // 使用自定义比较器实现大顶堆
        PriorityQueue heap = new PriorityQueue<>(new Comparator() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1; // 降序排列
            }
        });

        heap.add(3);
        heap.add(1);
        heap.add(2);

        // 输出堆顶元素(最大值)
        System.out.println(heap.peek()); // 输出: 3

        // 移除堆顶元素并输出
        System.out.println(heap.poll()); // 输出: 3
        System.out.println(heap.peek()); // 输出: 2
    }
}
总结
  • 堆的初始化:使用 PriorityQueue 类来初始化堆,PriorityQueue默认小顶堆。

  • 堆的相关函数addofferremovepollpeek 等方法用于操作堆。

  • 堆的原理:堆是一种完全二叉树,分为最大堆和最小堆,底层实现通常使用数组。

  • 运用堆进行排序:通过构建堆和反复取出堆顶元素实现排序。

刷题:

 数组中的第K个最大元素

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

思路:将数组中的所有元素添加到大顶堆中,然后第K大的元素就是将前K-1个元素从堆中poll出来,这个时候堆顶元素就是result。

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int result;
        PriorityQueue pq = new PriorityQueue<>(new Comparator(){
            @Override
            public int compare(Integer a,Integer b){
                return b-a;
            }
        });
        for(int num : nums){
            pq.add(num);
        }
        for(int i = k-1 ;i >0;i--){
            pq.poll();
        }
        result = pq.peek();
        return result;
    }
}

优化思路:继续使用大顶堆:不需要重写compare函数;Lambda 表达式的箭头 -> 后面的内容表示 Lambda 表达式的主体,(a,b)是给接口的参数。

PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a);

使用小顶堆:维护堆的大小只需要K就行,堆顶刚好是第K大的数。

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int result;
        PriorityQueue pq = new PriorityQueue<>();
        for(int num : nums){
            pq.add(num);
            if(pq.size()>k) pq.poll();
        }
        result = pq.peek();
        return result;
    }
}
前K个高频元素 

347. 前 K 个高频元素

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        HashMap map = new HashMap<>();
        for(int num: nums){
            if(map.containsKey(num)) map.put(num,map.get(num)+1);
            else{
                map.put(num,1);
            }
        }
        PriorityQueue pq = new PriorityQueue<>(new Comparator(){
            @Override
            public int compare(Integer a,Integer b)
            {
                return map.get(a)-map.get(b);
            }
        });
        for(Integer key :map.keySet()){
            if(pq.size()map.get(pq.peek())){
                pq.poll();
                pq.add(key);
            }
        }
        int[] result = new int[k];
        for(int i = 0;i
数据流的中位数 

 295. 数据流的中位数

思路:创建两个堆,一个大顶堆,一个小顶堆,大顶堆中根节点就是中位数,所以只有比根节点小的数能进去(这个时候很有可能第一个数很大,数全在大顶堆中,这个时候就要判断两个堆里面的个数,他俩最多大顶堆比小顶堆多一个数),小顶堆存放的是比中位数小的。

  •  big = new PriorityQueue<>((a,b)->b-a);这里调用了comparator接口,如果 compare(a, b) 返回正数,表示 a 应该排在 b 之后。当b-a>0,说明b比a大,a在b后面,是大顶堆。

class MedianFinder {
    PriorityQueue big;
    PriorityQueue small;
    public MedianFinder() {
        big = new PriorityQueue<>((a,b)->b-a);
        small = new PriorityQueue<>();        
    }
    
    public void addNum(int num) {
        if(big.isEmpty()||numsmall.size()+1) small.add(big.poll());
        }
        else{
            small.add(num);
            if(big.size()

你可能感兴趣的:(java,开发语言)