[路飞]_数组中的第K个最大元素

「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战

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

题目介绍

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例1

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
复制代码

示例2

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
复制代码

提示:

  • 1 <= k <= nums.length <= 10^4
  • -10^4 <= nums[i] <= 10^4

解题思路

思路一:直接排序

此题给了一个整数数组 nums,可以直接对整数数组 nums 进行升序排序或者降序排序,对数组进行排序有很多种方法,这里不做一一介绍,用最简单的 sort 排序进行解答

解题步骤

  1. nums 数组进行升序排序
  2. 返回排序后数组的下标为 nums.length - k 的值

解题代码

var findKthLargest = function(nums, k) {
    nums.sort((a, b) => a - b)
    return nums[nums.length - k]
};
复制代码

思路二:小顶堆

本题要找出数组中第K个最大元素,因此可以维护一个大小为 K 的小顶堆,当小顶堆的大小小于 K 时,直接往小顶堆中插入元素,然后向上调整维护小顶堆的结构,如果小顶堆的大小等于 K,那么只有比小顶堆的堆顶元素大的值才能够替换堆顶元素的位置进入小顶堆中,然后向下调整维护小顶堆的结构,最后当遍历完整个 nums 数组,返回堆顶元素即为数组中的第 K 个最大元素

解题步骤

  1. 创建小顶堆 minHeap,大小为 k
  2. 遍历整个 nums 数组中的整数,将所有的整数插入到小顶堆中
  3. 返回小顶堆 minHeap 的堆顶元素

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

解题代码

var findKthLargest = function(nums, k) {
    // 创建一个大小为 k 的小顶堆
    const minHeap = new Heap(k)
    // 将所有整数插入到小顶堆中
    while(nums.length) {
        minHeap.push(nums.pop())
    }
    // 返回小顶堆的堆顶元素
    return minHeap.pop()
};

class Heap {
    constructor(k) {
        this.arr = []
        this.k = k
    }

    // 返回小顶堆当前大小
    size() {
        return this.arr.length
    }

    // 向小顶堆中插入元素
    push(val) {
        if (this.size() < this.k) {
            this.arr.push(val)
            this._sortBack()
        } else if (val > this.arr[0]) {
            this.arr[0] = val
            this._sortFront()
        }
    }

    // 弹出小顶堆的堆顶元素
    pop() {
        const val = this.arr[0]
        const back = this.arr.pop()
        if (this.arr.length) {
            this.arr[0] = back
            this._sortFront()
        }
        return val
    }

    // 从小顶堆尾部向上调整小顶堆的结构
    _sortBack() {
        let i = this.arr.length - 1
        while(i > 0 && this.arr[i] < this.arr[Math.floor((i - 1) / 2)]) {
            [this.arr[i], this.arr[Math.floor((i - 1) / 2)]] = [this.arr[Math.floor((i - 1) / 2)], this.arr[i]]
            i = Math.floor((i - 1) / 2)
        }
    }

    // 从小顶堆顶部向下调整小顶堆的结构
    _sortFront() {
        let i = 0 
        while (i * 2 + 1 < this.size()) {
            let temp = i
            if (this.arr[temp] > this.arr[i * 2 + 1]) temp = i * 2 + 1
            if (i * 2 + 2 < this.size() && this.arr[temp] > this.arr[i * 2 + 2]) temp = i * 2 + 2
            if (temp === i) break
            [this.arr[i], this.arr[temp]] = [this.arr[temp], this.arr[i]]
            i = temp 
        }
    }
}
复制代码

Guess you like

Origin juejin.im/post/7061270317443842055