算法题解-数组中的第K个最大元素

149 阅读3分钟

题目

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

输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4

题解

第一种

我们在partation函数中先声明三个变量,x变量作为分区的基准值默认值为s参数中的r位置值,然后我们在声明两个指针i和j,分别指向左边界和右边界,然后我们使用两个while循环分别找到第一个大于等于x的元素和第一个小于x的元素并将它们交换位置,我们不断重复这个过程,直到i和j相遇,我们将基准值x放到i的位置上,并返回i,函数findKthLargest接收两个参数,分别是数组nums和目标位置k,我们在函数中先声明两个指针low和high,分别指向数组的左右边界,然后我们使用while循环不断将数组分为两部分,直到找到目标位置为止,在每一轮循环中,我们先调用partation函数将数组分为两部分,并得到基准值x的位置i,然后我们将目标位置转换为数组下标,如果i小于目标位置,我们则在右半部分继续查找,如果i大于目标位置,我们则在左半部分继续查找,如果i等于目标位置,我们则直接返回x,如果没有找到目标位置,我们则返回-1即可

function partation(s, l, r) {
  let x = s[r]
  let i = l
  let j = r
  while (i < j) {
    while (i < j && s[i] <= x) {
      i++
    }
    if (i < j) {
      s[j] = s[i]
      j--
    }
    while (i < j && s[j] > x) {
      j--
    }
    if (i < j) {
      s[i] = s[j]
      i++
    }
  }
  s[i] = x
  return i
}
function findKthLargest(nums, k) {
  let low = 0
  let high = nums.length - 1
  while (low <= high) {
    let i = partation(nums, low, high)
    let target = nums.length - k
    if (i < target) {
      low = i + 1
    } else if (i > target) {
      high = i - 1
    } else {
      return nums[i]
    }
  }
  return -1
}

第二种

我们这里使用快排的思想进行实现,我们在findKthLargest的函数中声明了一个名为traversal的递归函数,这个函数接受三个参数,一个数组nums,一个起始位置start和一个结束位置end,在函数中我们先判断start是否大于end,如果是我们则直接返回,否则我们就将数组中的第一个元素作为当前元素current,我们在声明一个变量index表示当前元素的索引,我们进行遍历数组中从start+1到end的元素,如果当前元素比current小,我们则将index加1并将当前元素和nums[index]交换位置,然后我们将当前元素和nums[index]交换位置,这样数组就被分为了两个部分,左边的元素都比nums[index]小,右边的元素都比nums[index]大,然后我们计算出目标位置target,如果index等于target,我们则直接返回nums[index],如果index大于target,我们则递归调用traversal函数,查找数组左半部分中第k大的元素,否则递归查找数组右半部分中第k大的元素,最后,我们将traversal函数返回值返回出去即可

function findKthLargest(nums, k) {
    function traversal(nums, start, end){
        if(start > end) return
        let current = nums[start]
        let index = start
        for(let i = start + 1; i <= end; i ++){
            if(current > nums[i]){
                index ++
                [nums[i], nums[index]] = [nums[index], nums[i]]
            }
        }
        [nums[start], nums[index]] = [nums[index], nums[start]]
        let target = nums.length - k
        if(index === target) return nums[index]
        return index > target ? traversal(nums, start, index) : traversal(nums, index + 1, end)
    }
    return traversal(nums, 0, nums.length - 1)
};

坚持努力,无惧未来!