1. let findKthLargest = function(nums, k) {
  2. // 从 nums 中取出前 k 个数,构建一个小顶堆
  3. let heap = [,], i = 0
  4. while(i < k) {
  5. heap.push(nums[i++])
  6. }
  7. buildHeap(heap, k)
  8. // 从 k 位开始遍历数组
  9. for(let i = k; i < nums.length; i++) {
  10. if(heap[1] < nums[i]) {
  11. // 替换并堆化
  12. heap[1] = nums[i]
  13. heapify(heap, k, 1)
  14. }
  15. }
  16. // 返回堆顶元素
  17. return heap[1]
  18. };
  19. // 原地建堆,从后往前,自上而下式建小顶堆
  20. let buildHeap = (arr, k) => {
  21. if(k === 1) return
  22. // 从最后一个非叶子节点开始,自上而下式堆化
  23. for(let i = Math.floor(k/2); i>=1 ; i--) {
  24. heapify(arr, k, i)
  25. }
  26. }
  27. // 堆化
  28. let heapify = (arr, k, i) => {
  29. // 自上而下式堆化
  30. while(true) {
  31. let minIndex = i
  32. if(2*i <= k && arr[2*i] < arr[i]) {
  33. minIndex = 2*i
  34. }
  35. if(2*i+1 <= k && arr[2*i+1] < arr[minIndex]) {
  36. minIndex = 2*i+1
  37. }
  38. if(minIndex !== i) {
  39. swap(arr, i, minIndex)
  40. i = minIndex
  41. } else {
  42. break
  43. }
  44. }
  45. }
  46. // 交换
  47. let swap = (arr, i , j) => {
  48. let temp = arr[i]
  49. arr[i] = arr[j]
  50. arr[j] = temp
  51. }

构建最小堆

  1. /**
  2. * @param {number[]} nums
  3. * @param {number} k
  4. * @return {number}
  5. */
  6. class MinHeap {
  7. constructor() {
  8. this.heap = [];
  9. }
  10. getParentIndex(i) {
  11. return (i - 1) >> 1; // 二进制
  12. }
  13. getLeftIndex(i) {
  14. return i * 2 + 1;
  15. }
  16. getRightIndex(i) {
  17. return i * 2 + 2;
  18. }
  19. shiftUp(index) {
  20. if (index === 0) { return; }
  21. const parentIndex = this.getParentIndex(index);
  22. if (this.heap[parentIndex] > this.heap[index]) {
  23. this.swap(parentIndex, index);
  24. this.shiftUp(parentIndex);
  25. }
  26. }
  27. swap(i1, i2) {
  28. const temp = this.heap[i1];
  29. this.heap[i1] = this.heap[i2];
  30. this.heap[i2] = temp;
  31. }
  32. insert(value) {
  33. this.heap.push(value);
  34. this.shiftUp(this.heap.length - 1);
  35. }
  36. pop() {
  37. this.heap[0] = this.heap.pop();
  38. this.shiftDown(0);
  39. }
  40. shiftDown(index) {
  41. const leftIndex = this.getLeftIndex(index);
  42. const rightIndex = this.getRightIndex(index);
  43. if (this.heap[leftIndex] < this.heap[index]) {
  44. this.swap(leftIndex, index);
  45. this.shiftDown(leftIndex);
  46. }
  47. if (this.heap[rightIndex] < this.heap[index]) {
  48. this.swap(rightIndex, index);
  49. this.shiftDown(rightIndex);
  50. }
  51. }
  52. peek() {
  53. return this.heap[0];
  54. }
  55. size() {
  56. return this.heap.length;
  57. }
  58. }
  59. // 大根堆排序
  60. let findKthLargest = function(nums, k) {
  61. let h = new MinHeap();
  62. nums.forEach(c => {
  63. h.insert(c);
  64. while(h.size()>k){
  65. h.pop()
  66. }
  67. })
  68. return h.peek();
  69. };

堆排序

https://github.com/sisterAn/JavaScript-Algorithms/issues/60