返回

巧解LeetCode 239:滑动窗口最大值,二叉堆显神通!

前端

引言

LeetCode上大名鼎鼎的239题,考察的是在滑动窗口内寻找最大值的经典问题。而二叉堆作为一种高效的数据结构,将在此题中大显神通,助你轻松攻克。

二叉堆简介

二叉堆是一种完全二叉树,其元素按照特定规则排序。大顶堆中,每个节点的值均大于其子节点的值,而小顶堆中则相反。二叉堆支持高效的插入、删除和查找最大值/最小值操作。

二叉堆解法

此题的解法思路如下:

  1. 初始化一个大顶堆,用于存储窗口内的元素。
  2. 窗口从数组中移动时:
    • 移出窗口左端的元素(从堆中删除)。
    • 移入窗口右端的元素(插入堆中)。
  3. 每次将元素插入堆后,从堆中取出最大值即可得到窗口内的最大值。

JavaScript实现

/**
 * 使用二叉堆求滑动窗口最大值
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
const maxSlidingWindow = (nums, k) => {
  const heap = new MaxHeap();
  const result = [];

  for (let i = 0; i < nums.length; i++) {
    if (i >= k) heap.delete(nums[i - k]);
    heap.insert(nums[i]);
    result.push(heap.max());
  }

  return result;
};

// 大顶堆类
class MaxHeap {
  constructor() {
    this.heap = [];
  }

  insert(val) {
    this.heap.push(val);
    this.siftUp(this.heap.length - 1);
  }

  delete(val) {
    const index = this.heap.indexOf(val);
    if (index < 0) return;
    this.swap(index, this.heap.length - 1);
    this.heap.pop();
    this.siftDown(index);
  }

  max() {
    return this.heap[0];
  }

  siftUp(index) {
    while (index > 0) {
      const parentIndex = Math.floor((index - 1) / 2);
      if (this.heap[index] > this.heap[parentIndex]) {
        this.swap(index, parentIndex);
        index = parentIndex;
      } else break;
    }
  }

  siftDown(index) {
    while (index < this.heap.length) {
      const leftIndex = 2 * index + 1;
      const rightIndex = 2 * index + 2;
      let maxIndex = index;
      if (leftIndex < this.heap.length && this.heap[leftIndex] > this.heap[maxIndex]) {
        maxIndex = leftIndex;
      }
      if (rightIndex < this.heap.length && this.heap[rightIndex] > this.heap[maxIndex]) {
        maxIndex = rightIndex;
      }
      if (maxIndex === index) break;
      this.swap(index, maxIndex);
      index = maxIndex;
    }
  }

  swap(i, j) {
    const temp = this.heap[i];
    this.heap[i] = this.heap[j];
    this.heap[j] = temp;
  }
}

结语

二叉堆的强大之处在于其时间复杂度为O(logN),使算法在面对大规模数据时也能保持高效。希望本篇文章能为你提供一个清晰的理解,助你轻松攻破239题!

SEO关键词: