看了好多面经 发现手写数组堆已经考了不少遍了!怎么能还不会呢?今天必须把它拿下!
快速回顾:1.堆是个完全二叉树 2.堆的父节点要小于左右子节点 (仅限最小堆,最大堆要 "大于")
首先我会通过通俗易懂的方式讲解堆的**主要**思路,切忌一上来就死怼代码!(欸欸,完全不了解堆的数据结构 赶快3w baidu.扛母 去啊!!!这里只是复习回顾哇)
首先 仅针对这道题 往里加的情况 那么堆有两种情况:
1. 堆没满
2. 堆满了
明白以上两点,就理解了50%啦!怎么样 通俗易懂吧
接着继续分析两种情况:
堆没满的话,直接从末尾(tail)加入一个新的值,通过 与 父节点比较谁小,小的话交换,大的话break, 我把这个过程称为 up
堆满的话,如果比首部大,则与首部(下标为0)直接交换,通过判断左右节点是否有比它小的,有就与更小的交换,没有就break, 我把这个过程称为 down
思路OK,代码的实现 岂不是信手拈来?
咦?就这

**面试前给自己试试手! 希望大家都能有个满意的offer~**
class Solution {
public int findKthLargest(int[] nums, int k) {
MyPriorityQueue pq = new MyPriorityQueue(k);
for (int num : nums) {
pq.add(num);
}
return pq.peek();
}
class MyPriorityQueue {
private int[] tree;
private int tail = -1; //尾指针,代表当前末尾
public MyPriorityQueue(int k) { //最小堆!!!!所以以下思路都是以最小堆展开的,最大堆反过来就行
tree = new int[k];
}
void add(int val) {
if (tail == -1) {
tree[++tail] = val; //一开始没数据 直接加
return;
}
if (tail == tree.length - 1) {//正如上面分析 满了我就往下走(down),没满我就往上爬 (up)
down(val);
} else {
up(val);
}
}
private void up(int val) {
tree[++tail] = val;
int index = tail;
while(index != 0){ //爬到顶就没有了 因为自己就是万子之父
int parent = getParent(index);
if (tree[parent] <= tree[index]){
return;
}
swap(parent, index);
index = parent;
}
}
private void down(int val) {
if (val < tree[0]) return;
int n = tree.length, index = 0;
tree[index] = val;
while (true){
int left = getLeft(index);
int right = getRight(index);
if (left >= n) break; // 左节点下标都超了 直接返回,不理解这里的同学请注意:堆是个完全二叉树(敲黑板)
if (right >= n){
if (tree[left] >= tree[index]) break; // 右节点超了只能对比左节点咯
swap(left, index);
break;
}else {
int minIndex = tree[left] < tree[right]? left : right; //找出两个值最小的节点
if (tree[minIndex] >= tree[index]) break;//最小的还比我大,那我就没有必要进行往下了。
swap(minIndex, index);
index = minIndex;
}
}
}
int peek(){
return tail >= 0? tree[0] : -1;
}
private int getParent(int index){
//return (index / 2) - ((index % 2) == 0? 1 : 0); 等价于下面的公式
return (index >> 1) - ((index & 1) == 0? 1 : 0); //获取父节点下标
}
private int getLeft(int index){
//return (index * 2) + 1; 等价于下面的公式
return (index << 1) + 1; //获取左节点下标
}
private int getRight(int index){
//return (index * 2) + 2; 等价于下面的公式
return (index << 1) + 2;
}
private void swap(int index1, int index2){
int t = tree[index1];
tree[index1] = tree[index2];
tree[index2] = t;
}
}
}