ts算法题解(第44天)--- leetcode 215. 数组中的第K个最大元素

162 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情

前言

每天一道算法题,死磕算法

题目

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

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

示例 1:

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

分析

  1. 这个题目可能大家的第一反应是我排序一下,然后找到第 k 个最大的元素不就可以了么。是的,也没错,但我们有没有更简单的方法呢。答案是有的,就是在没有排序完成之前我们就找到第k个最大的元素

  2. 排序的算法哪个时间复杂度好一些呢,答案是快速排序、归并排序、堆排序,他们的时间复杂度都是O(nlogn),我们今天选用一下快速排序

  3. 然后我们使用快速排序+二分查找的模式来解决一下这个问题,二分查找也很好理解,就是如何等于我们想要找的数,就返回,没找到的话,继续缩小范围在循环在找

首先我们来回忆一下快速排序怎么写,具体的可以参考我的这篇文章绝对记得住的各种排序算法(中)

function partition(nums:number[], left, right):number{
    let point = nums[left];
    let i = left+1,j=right;
    // 为了把所有的情况覆盖到,只有i>j的时候跳出循环
    while(i<=j){
      while(i<right && nums[i]<=point){
        i++;
      }
      // 此 while 结束时恰好 nums[i] > pivot
      while(j>left && nums[j]>point){
        j--;
      }
      // 此 while 结束时恰好 nums[j] <= pivot
      // 此时 [lo, i) <= pivot && (j, hi] > pivot
      if(i >= j){
        break;
      }
      
     [nums[i],nums[j]]=[nums[j],nums[i]];
    }
    // 此时j等于point
    [nums[left],nums[j]] = [nums[j],nums[left]];
    return j;
  }
  
  function quickSort(nums:number[], left, right){
      if(left>right){
        return;
      }
      let mid = partition(nums,left,right);
      quickSort(nums,mid+1,right);
      quickSort(nums,left,mid-1);

    }

二分查找也复习一下

function search(nums: number[], target: number): number {
    let left:number =0;
   
    let right:number = nums.length-1;

    while(left<=right){
        let mid:number = left+Math.floor((right-left)/2);
        if(target===nums[mid]){
            return mid;
        }else if(target<nums[mid]){
            right = mid - 1;
        }else if(target>nums[mid]){
            left = left+1;
        }
    }
    return -1;
};


题解

就是把上面两者合成一下

function partition(nums:number[], left, right):number{
    let point = nums[left];
    let i = left+1,j=right;
    while(i<=j){
      while(i<right && nums[i]<=point){
        i++;
      }
      while(j>left && nums[j]>point){
        j--;
      }
      if(i >= j){
        break;
      }
     [nums[i],nums[j]]=[nums[j],nums[i]];
    }
    // 此时j等于point
    [nums[left],nums[j]] = [nums[j],nums[left]];
    return j;
  }

function findKthLargest(nums: number[], k: number): number {
    let n = nums.length;
    let targetIndex = n - k;
    let left = 0, right = nums.length-1;
    while(left<=right){
        let mid = partition(nums,left,right);
        if(mid === targetIndex){
            console.log(nums);
            console.log(targetIndex);
            return nums[mid];
        }else if(targetIndex>mid){
            left = mid +1;
        }else{
            right = mid-1;
        }
    }
    return -1;
};

参考