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();
};
相关推荐
就叫_这个吧40 分钟前
java springcloud熔断降级组件sentinel基础应用及nacos持久化处理
java·spring cloud·nacos·sentinel
SimonKing1 小时前
Apache Fory JSON或许可以替代FastJson
java·后端·程序员
程序员良辰1 小时前
【TongWeb7的M11】 首次登录密码修改 & 开启控制台远程访问
java·中间件·tomcat
lichenyang4531 小时前
NestJS + Socket.IO 鉴权、用户房间与幂等邀请
前端·后端
吴声子夜歌1 小时前
Java面试——设计模式(四)
java·设计模式·面试
paopaokaka_luck1 小时前
基于springboot3+vue3+uniapp的剧本杀预约小程序(AI角色对话、协同过滤算法、地图Api、Echarts图形化分析)
java·前端·spring boot·学习·echarts
lichenyang4531 小时前
React 实时通知与异步竞态处理
前端·后端
一嘴一个橘子1 小时前
idea 的 双击Shift 全局搜索
java·ide·intellij-idea
nvvas1 小时前
最新版 IntelliJ IDEA 全面介绍:面向现代 Java 开发者的智能 IDE
java·ide·intellij-idea