Leetcode刷题——排序(2/16)

这篇博客介绍了如何使用快速选择和堆排序算法解决KthElement(第K个元素)和TopKElements(K个最小元素)问题。快速选择在平均情况下具有O(N)的时间复杂度,而堆排序则能通过建立大顶堆找到TopKElements。两种方法在适当调整后均可应用于这两种问题。示例中展示了在数组[3,2,1,5,6,4]中找到第2个最大元素(即第5小元素)的过程,输出结果为5。
摘要由CSDN通过智能技术生成

快速选择

用于求解 Kth Element 问题,也就是第 K 个元素的问题。
可以使用快速排序的 partition() 进行实现(略有区别)。需要先打乱数组,否则最坏情况下时间复杂度为 O(N2)。
在每执行一次的时候,比较基准值位置是否在 n-k 位置上,如果小于 n-k ,则第 k 个最大值在基准值的右边,我们只需递归基准值右边的子序列即可;如果大于 n-k ,则第 k 个最大值在基准值的做边,我们只需递归基准值左边的子序列即可;如果等于 n-k ,则第 k 个最大值就是基准值

用于求解 TopK Elements 问题,也就是 K 个最小元素的问题。使用最小堆来实现 TopK 问题,最小堆使用大顶堆来实现,大顶堆的堆顶元素为当前堆的最大元素。实现过程:不断地往大顶堆中插入新元素,当堆中元素的数量大于 k 时,移除堆顶元素,也就是当前堆中最大的元素,剩下的元素都为当前添加过的元素中最小的 K 个元素。插入和移除堆顶元素的时间复杂度都为 log2N。

堆也可以用于求解 Kth Element 问题,得到了大小为 K 的最小堆之后,因为使用了大顶堆来实现,因此堆顶元素就是第 K 大的元素。

快速选择也可以求解 TopK Elements 问题,因为找到 Kth Element 之后,再遍历一次数组,所有小于等于 Kth Element 的元素都是 TopK Elements。

可以看到,快速选择和堆排序都可以求解 Kth Element 和 TopK Elements 问题

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

Input: [3,2,1,5,6,4] and k = 2
Output: 5

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
数组方法:

var findKthLargest = function (nums, k) {
    return nums.sort((a, b) => b - a)[k - 1];
};

堆:

在这里插入代码片

快速选择:

var findKthLargest = function (nums, k) {
    return quickSelect(nums, 0, nums.length - 1, nums.length - k);
};

function quickSelect(arr, left, right, k) {
    if (left < right) {
        let indexPivot = partition(arr, left, right);
        if (indexPivot === k) return arr[k];
        else if (indexPivot > k) return quickSelect(arr, left, indexPivot - 1, k);
        else if (indexPivot < k) return quickSelect(arr, indexPivot + 1, right, k);
    }
    return arr[left];
}

function partition(arr, left, right) {
    const pivot = arr[Math.floor((left + right) / 2)];
    while (left < right) {
        while (arr[left] < pivot) {
            left++;
        }
        while (arr[right] > pivot) {
            right--;
        }
        //为了让与主元相等的值多次换位,到其正确位置
        if (left < right) {
            [arr[left], arr[right]] = [arr[right], arr[left]];
        }
        //解决重复值导致的死循环
        if (arr[left] === arr[right] && left !== right) {
            left++;
        }
    }
    return left
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值