今天刷算法遇到这个题,之前都是用快排写的,然而这次准备用堆排序写却写不出来了,重新复习了一手写个博客总结一下。
B站上这个视频很不错https://www.bilibili.com/video/BV1Eb41147dK
//题解
function GetLeastNumbers_Solution(input, k)
{
function swap(i,j){
let temp = heap[i];
heap[i] = heap[j];
heap[j] = temp;
}
function percDown(index,N){
let root = heap[index];
let parent,child;
//为root找到合适的位置
for( parent=index; parent*2+1<N; parent=child){
child = parent*2+1;
//child为两个parent中值小的那个元素
if(child+1<N && heap[child+1]>heap[child])
child++;
if( root > heap[child] )//找到了合适位置break
break;
else
heap[parent] = heap[child];
}
heap[parent] = root;
}
let heap = input.slice(0,k);
//前k个元素建立最大堆
for(let i=Math.floor(k/2)-1; i>=0; i-- ){
percDown(i,k);//第i个到第N个为最大堆
}
for(let i=k; i<input.length; i++){
if(input[i]<heap[0]){
heap[0] = input[i];//新的元素比大顶堆的第一个还小的话,替换大顶堆的第一个元素,重新建堆
percDown(0,k);
}
}
return heap;
}
module.exports = {
GetLeastNumbers_Solution : GetLeastNumbers_Solution
};
//堆排序算法
function heapSort(arr) {
let len = arr.length;
//交换
function swap(arr, rootIndex, maxIndex) {
let temp = arr[rootIndex];
arr[rootIndex] = arr[maxIndex];
arr[maxIndex] = temp;
}
// 堆调整
function heapify(arr, index) {
let leftIndex = 2 * index + 1; //左子节点
let rightIndex = 2 * index + 2; //右子节点
let maxIndex = index;
if (leftIndex < len && arr[leftIndex] > arr[maxIndex]) {
maxIndex = leftIndex
}
if (rightIndex < len && arr[rightIndex] > arr[maxIndex]) {
maxIndex = rightIndex
}
if (maxIndex !== index) {
swap(arr, index, maxIndex);
heapify(arr, maxIndex); //此时父子节点已经交换 下面那层可能不满足大根堆了
}
}
for (let i = Math.floor(len / 2); i >= 0; i--) {
// 自顶向下进行堆调整
heapify(arr, i)
}
for (let j = len - 1; j >= 0; j--) {
len--;
swap(arr, 0, j);
heapify(arr, 0);
}
return arr;
}