1:创建优先级队列的方法
PriorityQueue<> heap = new PriorityQueue<>((a,b) -> a-b); 小根堆 差为负数,小的a放前面
PriorityQueue<> heap = new PriorityQueue<>((a,b) -> b-a); 大根堆
2:添加元素
offer()和add()都可以
在容量有限的 PriorityQueue 中,offer() 更安全,因为它会在队列已满时返回 false,而 add() 会抛出 IllegalStateException 异常。
3:弹出元素
.poll()
4:获取堆顶元素
.peek()
5:Collections.reverse()
逆序一个集合中的元素,返回类型为List
6:堆的大小
.size();
心得感悟:————大根堆不要纠结,就记住一个小根堆就行了,大根堆反过来就OK
1:用Pair类型巧妙的将咱们map数据结构和堆联系到了一起
2:此题提升了写堆的比较规则,在lambda表达式中,巧妙的运用compareTo()方法:使用方式——b.compareTo(a) b<a 返回负数 。
3:b.compareTo(a) b<a 返回负数 结合 (a,b)->{ (b.compareTo(a) } 花括号中是负数,创建的是大根堆 这个式子等价于 (a,b)-> (b-a)
4:为什么if条件中用的是equals()方法,而不是==,因为Integer是int的包装类型,是一个对象,==比较的是对象的引用地址值,equals()才能比较对象中属性的值
5:如果使用idea,没有内置Pair类,我们需要自己实现一个Pair
class Pair<K,V>{
private K key;
private V value;
public Pair(K key , V value){
this.key = key;
this.value = value;
}
public K getKey(){
return key;
}
public V getValue(){
return value;
}
}
class Solution {
public List<String> topKFrequent(String[] words, int k) {
//我的两个问题——1:怎么把map中的元素按照重写的比较规则放入到堆里面
//2:因为map中是键值对结构,但是堆只能放一个类型,怎么放是一个问题
//第一步:把所有字符串放入map中,map结构去重
Map<String,Integer> map = new HashMap<>();
for(String str : words){
map.put(str,map.getOrDefault(str,0)+1);
}
//第二步:new 一个堆 重写比较规则
PriorityQueue<Pair<String,Integer>> heap = new PriorityQueue<>(
(a,b)->{
//如果出现频次相同,按字母顺序返回,创建大根堆,可以理解成首字母更小的往堆的更深处放
if(a.getValue().equals(b.getValue())){
return (b.getKey().compareTo(a.getKey()));//对啊,compareTo方法怎么放啊
}
//依据频次创建小根堆
return (a.getValue()-b.getValue());
}
);
//第三步:遍历map,把元素放到堆里面
for(Map.Entry<String,Integer> entry : map.entrySet()){
heap.offer(new Pair<>(entry.getKey(),entry.getValue()));
if(heap.size() > k){
heap.poll();
}
}
//第四步:让堆不断弹出元素,注意逆序(不逆序就倒着填入数组),这里采用集合的方式
List<String> list = new ArrayList<>();
for(int i = 0 ; i < k ; i++){
String s = heap.peek().getKey();
list.add(s);
heap.poll();
}
Collections.reverse(list);
return list;
}
}
class Solution {
public int lastStoneWeight(int[] stones) {
//大根堆
PriorityQueue<Integer> heap = new PriorityQueue<>((a,b) -> b-a);
for(int x : stones){
heap.add(x);
}
while(heap.size() >= 2){
int a = heap.poll();
int b = heap.poll();
if(a != b){
heap.add(a - b);//先弹出的大
}
}
return heap.isEmpty() ? 0 : heap.peek();
}
}心得:
1:这道题可以体会全局成员变量的好处
2:老实说这个题目读完题,给我一种无从下手的感觉,写完代码后豁然开朗,不难

class KthLargest {
//创建全局成员变量
private PriorityQueue<Integer> heap;//默认为小根堆
private int _k;//堆的大小
public KthLargest(int k, int[] nums) {
heap = new PriorityQueue<>((a,b) -> a-b);
_k = k;
for(int i = 0 ; i < nums.length ; i++){
heap.offer(nums[i]);
if(heap.size() > _k){
heap.poll();
}
}
}
public int add(int val) {
heap.offer(val);
if(heap.size() > _k){
heap.poll();
}
return heap.peek();
}
}
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest obj = new KthLargest(k, nums);
* int param_1 = obj.add(val);
*/心得:
1:用大小根堆来处理数据流的中位数问题,算是开拓思路了
2:暴力解法就是用每次add一个元素之后就Arrays.sort();一下



class MedianFinder {
private PriorityQueue<Integer> left;//左边是大根堆,右边是小根堆
private PriorityQueue<Integer> right;
public MedianFinder() {
left = new PriorityQueue<>((a,b) -> b-a);
right = new PriorityQueue<>((a,b) -> a-b);
}
public void addNum(int num) {
if(left.size() == right.size()){
if(left.isEmpty() || num <= left.peek()){
left.offer(num);
}else if(num > left.peek()){
right.offer(num);
left.offer(right.poll());
}
}else if(left.size() - right.size() == 1){
if(num <= left.peek()){
left.offer(num);
right.offer(left.poll());
}else if(num > left.peek()){
right.offer(num);
}
}
}
public double findMedian() {
if(left.size() == right.size()){
double ret = ( left.peek() + right.peek() ) / 2.0;
return ret;
}else{
return left.peek();
}
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder obj = new MedianFinder();
* obj.addNum(num);
* double param_2 = obj.findMedian();
*/