DAILY DOCDAILY DOC
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
  • Array

    • 数组
    • 二分查找
    • moveZeros
  • Dynamic-programming

    • 动态规划
  • 刷题指南
  • String

    • 字符串
  • bitwise-operator

    • 位运算符
  • heap
  • history

    • [1014] 最佳观光组合
    • [1022] 从根到叶的二进制数之和
    • [104] 二叉树的最大深度
    • [11] 盛最多水的容器
    • [110] 平衡二叉树
    • [1227] 飞机座位分配概率
    • [129] 求根节点到叶节点数字之和
    • [1306] 跳跃游戏 III
    • [148] 排序链表
    • 155.最小栈
    • [165] 比较版本号
    • 1763. 最长的美好子字符串
    • [1870] 准时到达的列车最小时速
    • [199] 二叉树的右视图
    • [21] 合并两个有序链表
    • 215.数组中的第 k 个最大元素
    • [2306] 公司命名
    • [234] 回文链表
    • [2516] 每种字符至少取 K 个
    • [316] 去除重复字母
    • [3171] 找到按位或最接近 K 的子数组
    • [322] 零钱兑换
    • [41] 缺失的第一个正数
    • [44] 通配符匹配
    • [494] 目标和
    • [509] 斐波那契数
    • [518] 零钱兑换 II
    • [62] 不同路径
    • [676] 实现一个魔法字典
    • 70 爬楼梯
    • [718] 最长重复子数组
    • [78] 子集
    • [82] 删除排序链表中的重复元素 II
    • [871] 最低加油次数
    • [88] 合并两个有序数组
    • [887] 鸡蛋掉落
    • 958.二叉树的完全性检验
    • [98] 验证二叉搜索树
    • [983] 最低票价
    • leetcode practice
    • 约瑟夫问题
    • 移除重复节点
  • linked-list

    • 706. 设计哈希映射
    • 链表
  • stack

    • stack
  • tree

    • Tree Traversal
    • 二叉树的最近公共祖先
    • 二叉树
    • 题目
  • leetCode 刷题
  • 回溯
  • 排序算法

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

排序

最简单的方法是对数组进行排序,然后直接返回第 K 个最大的元素。

代码实现

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findKthLargest = function (nums, k) {
    nums.sort((a, b) => b - a);
    return nums[k - 1];
};

// 示例
console.log(findKthLargest([3, 2, 1, 5, 6, 4], 2)); // 输出 5

选择排序

details
var findKthLargest = function (nums, k) {
    //边界值处理
    if (nums.length <= 1) return nums[k - 1];
    //

    let i = 0;
    let temp = 0;
    while (i < nums.length) {
        let j = i;
        let maxIndex = i;

        while (j < nums.length) {
            if (nums[j] > nums[maxIndex]) {
                maxIndex = j;
            }
            j++;
        }

        // 交换i跟最大的元素
        if (i !== maxIndex) {
            temp = nums[i];
            nums[i] = nums[maxIndex];
            nums[maxIndex] = temp;
        }
        // console.log(JSON.stringify(nums), i, j, nums[maxIndex]);
        // 找到第K 个就结束了
        if (i >= k - 1) {
            return nums[k - 1];
        }
        i++;
    }
    return nums[k];
};

使用最小堆

可以使用最小堆来维护数组中最大的 K 个元素。这样堆顶元素就是第 K 个最大的元素。

代码实现

class MinHeap {
    constructor() {
        this.heap = [];
    }

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

    pop() {
        const min = this.heap[0];
        const end = this.heap.pop();
        if (this.heap.length > 0) {
            this.heap[0] = end;
            this.bubbleDown(0);
        }
        return min;
    }

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

    bubbleUp(index) {
        const element = this.heap[index];
        while (index > 0) {
            const parentIndex = Math.floor((index - 1) / 2);
            const parent = this.heap[parentIndex];
            if (element >= parent) break;
            this.heap[index] = parent;
            index = parentIndex;
        }
        this.heap[index] = element;
    }

    bubbleDown(index) {
        const length = this.heap.length;
        const element = this.heap[index];
        while (true) {
            let leftChildIndex = 2 * index + 1;
            let rightChildIndex = 2 * index + 2;
            let leftChild, rightChild;
            let swap = null;

            if (leftChildIndex < length) {
                leftChild = this.heap[leftChildIndex];
                if (leftChild < element) {
                    swap = leftChildIndex;
                }
            }

            if (rightChildIndex < length) {
                rightChild = this.heap[rightChildIndex];
                if ((swap === null && rightChild < element) || (swap !== null && rightChild < leftChild)) {
                    swap = rightChildIndex;
                }
            }

            if (swap === null) break;

            this.heap[index] = this.heap[swap];
            index = swap;
        }
        this.heap[index] = element;
    }
}

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findKthLargest = function (nums, k) {
    const minHeap = new MinHeap();
    for (let num of nums) {
        minHeap.push(num);
        if (minHeap.size() > k) {
            minHeap.pop();
        }
    }
    return minHeap.pop();
};

// 示例
console.log(findKthLargest([3, 2, 1, 5, 6, 4], 2)); // 输出 5

快速选择算法

快速选择算法类似于快速排序,通过分区操作来查找第 K 个最大的元素。

代码实现

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findKthLargest = function (nums, k) {
    const n = nums.length;
    return quickSelect(nums, 0, n - 1, n - k);
};

function quickSelect(arr, left, right, k) {
    if (left === right) return arr[left];

    let pivotIndex = partition(arr, left, right);
    if (k === pivotIndex) {
        return arr[k];
    } else if (k < pivotIndex) {
        return quickSelect(arr, left, pivotIndex - 1, k);
    } else {
        return quickSelect(arr, pivotIndex + 1, right, k);
    }
}

function partition(arr, left, right) {
    let pivot = arr[right];
    let pivotIndex = left;

    for (let i = left; i < right; i++) {
        if (arr[i] <= pivot) {
            [arr[i], arr[pivotIndex]] = [arr[pivotIndex], arr[i]];
            pivotIndex++;
        }
    }
    [arr[pivotIndex], arr[right]] = [arr[right], arr[pivotIndex]];
    return pivotIndex;
}

// 示例
console.log(findKthLargest([3, 2, 1, 5, 6, 4], 2)); // 输出 5

总结

  • 排序方法 时间复杂度为 O(nlog⁡n)O(n \log n)O(nlogn),适用于简单情况。
  • 堆方法 时间复杂度为 O(nlog⁡k)O(n \log k)O(nlogk),适用于处理大数据流。
  • 快速选择算法 时间复杂度为 O(n)O(n)O(n) 平均情况,最坏情况为 O(n2)O(n^2)O(n2),适用于需要高效处理的情况。
Last Updated:
Contributors: rosendo
Prev
[21] 合并两个有序链表
Next
[2306] 公司命名