问题描述:给出一个个元素的序列,求其中的第k小元素(即序列按升序排序后的第k个元素)。

中项(中间元素):一个序列的中项为该序列的第「n/2 小元素。

快速选择

基本思路:将一个数组的第一个元素为基准元素(pivotIndex),将数组中小于基准元素的,放在左边,大于的放在右边,当基准元素的索引=k-1的时候,此时基准元素的值就是第k小元素。

如果pivotIndex>k-1 就在右边递归找 如果pivotIndex<k-1 就在左边递归找

递归出口为数组长度为1

function findKthLargest(nums: number[], k: number): number {
    // 随机选择一个基准值(pivot)
    const pivot = nums[Math.floor(Math.random() * nums.length)];
    
    const left: number[] = [];   // 存放大于 pivot 的数
    const mid: number[] = [];    // 存放等于 pivot 的数
    const right: number[] = [];  // 存放小于 pivot 的数
 
    for (const num of nums) {
        if (num > pivot) left.push(num);
        else if (num < pivot) right.push(num);
        else mid.push(num);
    }
 
    // 情况 1:第 k 大在左边(大于 pivot 的部分)
    if (k <= left.length) {
        return findKthLargest(left, k);
    }
    // 情况 2:第 k 大就在中间(等于 pivot 的部分)
    if (k <= left.length + mid.length) {
        return pivot;
    }
    // 情况 3:第 k 大在右边(小于 pivot 的部分)
    // 注意:k 也要相应减去左边和中间已经排除掉的个数
    return findKthLargest(right, k - left.length - mid.length);
}

reference