JS实现堆 & 215.数组中的第K个最大元素

解决问题

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

最小堆(MinHeap)实现

核心性质: 父节点的值始终 <= 子节点的值,堆顶(index 0)永远是全局最小值。

底层结构: 用数组模拟完全二叉树,父子节点索引关系:

  • 父节点:(i - 1) / 2
  • 左子节点:2 * i + 1
  • 右子节点:2 * i + 2

时间复杂度:

  • push:O(log n) ------ 插入后上浮
  • pop:O(log n) ------ 删除堆顶后下沉
  • peek:O(1) ------ 直接读堆顶

核心操作说明:

  • bubbleUp(上浮):新元素插入到数组末尾后,如果比父节点小,就和父节点交换,一路向上直到满足堆性质。
  • sinkDown(下沉):堆顶被替换后,如果比子节点大,就和较小的子节点交换,一路向下直到满足堆性质。
  • push(插入):放到数组末尾,然后上浮到正确位置。
  • pop(弹出):取出堆顶 → 把数组最后一个元素移到堆顶 → 对新堆顶执行下沉操作。
  • peek(查看):直接返回堆顶(最小值),不弹出。

典型用法: 维护一个大小为 k 的最小堆,堆顶就是"最大的 k 个元素中的最小值",即第 k 大元素。遍历数组时,元素入堆,堆大小超过 k 就弹出堆顶(淘汰最小值),最终堆顶就是答案。

js 复制代码
class Heap {
    constructor() {
        this.heap = [];
    }

    bubbleUp(index) {
        let i = index;
        while(i > 0) {
            const parent = Math.floor((i - 1) / 2);
            if (this.heap[i] < this.heap[parent]) {
                [this.heap[i], this.heap[parent]] = [this.heap[parent], this.heap[i]];
                i = parent;
            } else {
                break
            }
        }
    }

    sinkDown(index) {
        while(true) {
            let smallestIndex = index;
            const left = 2 * index + 1;
            const right = 2 * index + 2;

            if (left < this.heap.length && this.heap[smallestIndex] > this.heap[left]) {
                smallestIndex = left;
            }
            if (right < this.heap.length && this.heap[smallestIndex] > this.heap[right]) {
                smallestIndex = right;
            }
            if (smallestIndex !== index) {
                [this.heap[smallestIndex], this.heap[index]] = [this.heap[index], this.heap[smallestIndex]];
                index = smallestIndex;
            } else {
                break;
            }
        }
    }

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

    pop() {
        const top = this.heap[0];
        const last = this.heap.pop();

        if (this.heap.length) {
            this.heap[0] = last;
            this.sinkDown(0);
        }

        return top;
    }

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

数组中的第K个最大元素解题方案为

js 复制代码
// 堆
function findKthLargest(nums: number[], k: number): number {
    class MinHeap {
        heap: number[];
        constructor() {
            this.heap = [];
        }

        bubbleUp(index) {
            let i = index;
            while (i > 0) {
                const parent = Math.floor((i - 1) / 2);
                if (this.heap[i] < this.heap[parent]) {
                    [this.heap[i], this.heap[parent]] = [this.heap[parent], this.heap[i]];
                    i = parent;
                } else {
                    break
                }
            }
        }

        sinkDown(index) {
            while (true) {
                let smallestIndex = index;
                const left = 2 * index + 1;
                const right = 2 * index + 2;

                if (left < this.heap.length && this.heap[smallestIndex] > this.heap[left]) {
                    smallestIndex = left;
                }
                if (right < this.heap.length && this.heap[smallestIndex] > this.heap[right]) {
                    smallestIndex = right;
                }
                if (smallestIndex !== index) {
                    [this.heap[smallestIndex], this.heap[index]] = [this.heap[index], this.heap[smallestIndex]];
                    index = smallestIndex;
                } else {
                    break;
                }
            }
        }

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

        pop() {
            const top = this.heap[0];
            const last = this.heap.pop();

            if (this.heap.length) {
                this.heap[0] = last;
                this.sinkDown(0);
            }

            return top;
        }

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

        size() {
            return this.heap.length;
        }
    }

    const heap = new MinHeap();

    nums.forEach((item) => {
        heap.push(item);
        if (heap.size() > k) {
            heap.pop();
        }
    });

    return heap.peek();
};
相关推荐
review44543几秒前
拿到 codex 第一步
前端·agent·vibecoding
用户3126874877206 分钟前
Java 对象内存布局:压缩指针、对齐填充与 JOL 实测
java
鶴哥只手遮天11 分钟前
jQuery 4.0 源码架构与工程实践-第 01 章 · 全景与工程结构:一个 20 岁库的自省
前端·javascript·jquery
东华果汁哥22 分钟前
【Spring AI 实战】从零开始调用大模型接口,构建 Java AI 应用
java·人工智能·spring
徐小夕27 分钟前
doc2docx方案,开源!
前端·vue.js·github
徐小夕32 分钟前
JitOFD:一款面向信创与档案场景的 Web 端 OFD 编辑器
前端·vue.js·github
Song_RsHt1 小时前
Redis 与微服务,什么场景下无可替代
java·redis·后端·学习·微服务
孟健1 小时前
Kimi K3.1 Pro 编程实测:3个月27万行代码,每年1.7万预算下如何9分钟修好顽固Bug
前端·开源·ai编程
学长毕设1 小时前
基于SpringBoot的建筑材料管理系统-附源码
java·spring boot·后端
inksci1 小时前
在线编辑表格,功能强大,json互转
前端·javascript·html