leetcode 215数组中第k个最大元素

127 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

给定整数数组 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

思路分析

首先我们在思考这类题目的时候可能第一想到的是对数组进行排序,然后获取第k个数字即可,但是排序的方法有很多种,但是其中大部分的方法都需要将数组整体排序后才能获取到我们想要的结果。

这个时候我们就可以考虑使用堆排序的方法来进行排序,堆排的好处在于,我们将元素组成堆结构,只需要关心最上层的数据就行了,中间元素不需要关心顺序。

这种结构就很适合获取第几个最大元素这一类的题

首先实现一个最大堆类,具有插入元素,获取元素父元素,交换元素等功能,向堆中插入一个元素后获取该元素的父元素,然后与父元素比较大小,如果大于父元素则交换位置,然后继续与新位置的父元素进行比较,直到元素小于父元素或者元素到堆顶了,然后在构建好堆之后,我们只需要将堆顶删除k-1次然后获取到数组的最上层元素就是数组中第k个最大元素。

代码实现

class hashMap {
  constructor() {
    this.arr = []
  }
  insert(val) {
    this.arr.push(val)
    this.shiftUp(this.arr.length - 1)
  }
  shiftUp(index) {
    if (index === 0) return
    let parentIndex = this.getParentIndex(index)
    if (this.arr[parentIndex] < this.arr[index]) {
      this.swap(index, parentIndex)
      this.shiftUp(parentIndex)
    }
  }
  shiftDown(index) {
    let leftIndex = this.getLeftChild(index)
    let rightIndex = this.getRightChild(index)
    if (this.arr[leftIndex] > this.arr[index]) {
      this.swap(index, leftIndex)
      this.shiftDown(leftIndex)
    }
    if (this.arr[rightIndex] > this.arr[index]) {
      this.swap(index, rightIndex)
      this.shiftDown(rightIndex)
    }
  }
  getLeftChild(index) {
    return index * 2 + 1
  }
  getRightChild(index) {
    return index * 2 + 2
  }
  getParentIndex(index) {
    return Math.floor(index - 1 / 2)
  }
  swap(index, parentIndex) {
    let tmp = this.arr[parentIndex]
    this.arr[parentIndex] = this.arr[index]
    this.arr[index] = tmp
  }
  pop() {
    this.arr[0] = this.arr.pop()
    this.shiftDown(0)
  }
}

var findKthLargest = function(nums, k) {
    let min = new hashMap()
    nums.forEach(item=>{
        min.insert(item)
    })
    for(let i = 1; i < k; i++){
        min.pop()
    }
    return min.arr[0]
};