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();
};
相关推荐
Wang's Blog2 小时前
Java 项目实战: 外卖平台优化-Nginx配置文件结构与块层级
java·开发语言·nginx
福兮说3 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
\光辉岁月/3 小时前
5.java-数组
java·开发语言
谢亮_vipxieliang4 小时前
Spring 事务失效的常见场景
java·开发语言·数据库·spring boot
郑州光合科技余经理4 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
2601_962071574 小时前
类变量和全局变量的生命周期有什么区别?
java·开发语言·jvm
code2cat4 小时前
Java进阶篇之AtomicReference:一次替换引用,读到一份完整状态
java·并发编程·不可变对象·atomicreference
专业程序开发源4 小时前
springboot简历管理系统81389-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·php·课程设计
Wang's Blog4 小时前
Java 项目实战: 外卖平台优化-前后端分离开发模式与工程拆分
java·开发语言
小呆呆6665 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试