堆排序及Leetcode题目

584 阅读1分钟

讲解

堆特性

  • 完全二叉树
  • 任意一个父节点的值都大于子节点

构建堆

  • 堆化:对指定节点进行堆化,使得当前节点大于其子节点【注意:进行过堆化后要对子节点也进行堆化,保证整棵树满足堆特性】
  • 堆:自下而上,从最后一个节点开始,依次对每个节点作堆化。

image.png

堆排序

  • 堆的特性,使得整棵树的最大值在堆顶。交换堆顶和堆尾的值后,砍去堆尾(即树长度 - 1)后对整棵树进行堆化,再次使得整棵树的最大值在堆顶。重复操作,实现树按照从小到大的顺序从堆顶到堆尾。

image.png

215.数组中的第K个最大元素

  • 代码
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
 var findKthLargest = function(nums, k) {
  heapSort(nums, nums.length);
  return nums[nums.length - k];
};

const swap = (arr, i, j) => {
  const temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}

const heapify = (tree, n, i) => {
  if (i >= n) {
    return;
  }

  const leftChildNode = 2 * i + 1;
  const rightChildNode = 2 * i + 2;
  let max = i;

  if (leftChildNode < n && tree[leftChildNode] > tree[max]) {
    max = leftChildNode;
  }

  if (rightChildNode < n && tree[rightChildNode] > tree[max]) {
    max = rightChildNode;
  }

  if (max !== i) {
    swap(tree, max, i);
    heapify(tree, n, max);
  }
} 

const buildHeap = (tree, n) => {
  const lastNode = n - 1;
  const parentNode = Math.floor((lastNode - 1) / 2);

  for(let i = parentNode; i >= 0; i--) {
    heapify(tree, n, i);
  }
}

const heapSort = (tree, n) => {
  buildHeap(tree, n);

  for(let i = n - 1; i > 0; i--) {
    swap(tree, 0, i);
    heapify(tree, i, 0);
  }
}
  • 缺陷: 对整棵树进行了排序,造成浪费。