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();
};
相关推荐
郑州光合科技余经理17 小时前
本地生活系统:多业务订单字段怎么分账本导出
java·开发语言·前端·数据库·uni-app·php·ai编程
YangYang9YangYan18 小时前
2026 校招审计风控岗位 JD 拆解,工具、专业能力与面试考点
java·大数据·人工智能·数据分析
wuminyu1 天前
Kafka中sendfile与mmap实现机制解析
java·linux·c语言·jvm·c++
怕浪猫1 天前
FDE 如何正确解决现场项目工程性的问题
前端·后端·ai编程
西瓜太郎12341 天前
外层模型卡片与分组详情成功率不一致,应该怎么排查?
前端·typescript·go·软件工程·react
GreenTea1 天前
vLLM 与 SGLang KV Cache 底层实现机制深度调研报告
前端·后端·算法
考虑考虑1 天前
Java实现hmacsha256加密算法
java·后端·java ee
captain3761 天前
▲网络原理(2)-TCP
java·服务器·网络·tcp/ip·java-ee
MetaLite1 天前
SpringBoot接口分层规范-外网网关内部服务与参数边界
java·数据库·spring boot
Co_Hui1 天前
Java 线程状态
java