【Java数据结构】——堆(找出用于解决最大/最小的n个元素,或者求中位数)
一.堆的介绍
堆是一种基于树的数据机构,用完全二叉树实现(除了最后一层都必须填满)
由于它的特性可以用数组来存储元素。
二.建堆(建立大顶堆/小顶堆)
与更大的一个孩子进行交换,直至停止。
堆的力扣题
1.数据流取最大的第K个数
public class StreamKBigNum {private MinHeap minHeap;public StreamKBigNum(int k, int[] nums) {minHeap = new MinHeap(k);}public int add(int val) {if (!minHeap.isFull()){minHeap.offer(val);}else if (minHeap.peek() < val){minHeap.replace(val);}return minHeap.peek();}public static void main(String[] args) {StreamKBigNum test = new StreamKBigNum(3, new int[]{});System.out.println(test.add(3)); // [3] 3System.out.println(test.add(5)); // [3 5] 3System.out.println(test.add(10));System.out.println(test.add(9));System.out.println(test.add(4));}
}
2.数据流取数据的中位数
public class MediumNum {//大顶堆private PriorityQueue<Integer> left = new PriorityQueue<>((a, b) -> Integer.compare(b, a));//小顶堆private PriorityQueue<Integer> right = new PriorityQueue<>();public void addNum(int num) {if (left.size() == right.size()){right.offer(num);Integer poll = right.poll();left.offer(poll);}else {left.offer(num);right.offer(left.poll());}}public double findMedian() {if (left.size() == right.size()){return (left.peek() + right.peek()) / 2.0;}else {return left.peek();}}public static void main(String[] args) {MediumNum test = new MediumNum();test.addNum(1);test.addNum(2);test.addNum(3);test.addNum(7);test.addNum(8);test.addNum(9);System.out.println(test.findMedian());test.addNum(10);System.out.println(test.findMedian());test.addNum(4);System.out.println(test.findMedian());}
}
3.收集hashmap缓存中出现频率最高的n个字符串
public void QueryTopN(List<String> input, List<String> result, int n) {// 统计每个字符串出现的次数Map<String, Integer> frequencyMap = new HashMap<>();for (String str : input) {frequencyMap.put(str, frequencyMap.getOrDefault(str, 0) + 1);}// 小顶堆,用于存储出现次数最多的n个字符串PriorityQueue<Map.Entry<String, Integer>> minHeap = new PriorityQueue<>((e1, e2) -> e1.getValue().compareTo(e2.getValue()));for (Map.Entry<String, Integer> entry : frequencyMap.entrySet()) {if (minHeap.size() < n) {minHeap.offer(entry);} else if (entry.getValue() > minHeap.peek().getValue()) {minHeap.poll();minHeap.offer(entry);}}// 将堆中的元素取出并反转,得到出现次数从多到少的结果List<String> temp = new ArrayList<>();while (!minHeap.isEmpty()) {temp.add(minHeap.poll().getKey());}Collections.reverse(temp);result.addAll(temp);}