面试经典 150 题 1 —(堆)— 215. 数组中的第K个最大元素(快排、桶排、堆排)

本文介绍了四种寻找数组中第K个最大元素的方法,包括快速排序、插入排序、堆排序和桶排序,分析了它们的时间复杂度和实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

在这里插入图片描述

方法一:sort(用到了快速排序,但不仅仅只用了快速排序,还结合了插入排序和堆排序)
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end(), [](int a, int b)->bool {return a > b;});
        return nums[k - 1];
    }
};
方法二:快速排序(在最糟情况下,其运行时间为O(n^2);在平均情况下,快速排序的运行时间为O(nlogn))
class Solution {
public:
    // 快速排序
        void quickSort(vector<int>& nums, int start, int end){
        if (start < end) {
            int base = nums[start];//以要进行排序数组第0个元素为base
            int left = start;//左指针
            int right = end;//右指针
            while (left < right) {
                //从右向左找,比base大,right--
                while (left< right && nums[right] >= base) {
                    right--;
                }
                //比base小,替换left所在位置的数字
                nums[left] = nums[right];
                //从左向右找,比base小,left++
                while (left < right && nums[left] <= base){
                    left++;
                }
                //比base大,替换right所在位置的数字
                nums[right] = nums[left];
            }
            nums[left] = base;//此时left=right,用base替换这个位置的数字

            //排列比base小的数字的数组
            quickSort(nums, start, left - 1);
            //排列比base大的数字的数组
            quickSort(nums, left + 1, end);
        }
    }
    int findKthLargest(vector<int>& nums, int k) {
        quickSort(nums, 0, nums.size() - 1);
        return nums[nums.size() - k];
    }
};
方法三:桶排序(运行时间为O(n))
class Solution {
public:
    // 桶排序
    int findKthLargest(vector<int>& nums, int k) {
        // -10000 <= nums[i] <= 10000
        vector<int> buckets(20001, 0);
        for(int i = 0; i < nums.size(); i++){
            // nums[i]可能是负数,而且-10000 <= nums[i],所以将nums[i]需要加上一个偏移量10000
            buckets[nums[i] + 10000]++;
        }

        for(int i = 20000; i >=0; i--){
            if(buckets[i] == 0){
                continue;
            }
            else{
                k = k - buckets[i];
                if(k <= 0){
                    return i - 10000;
                }
            }
        }

        return 0;
    }
};
方法四:堆排序(时间复杂度取决于树的高度h。而完全二叉树的树的高度为[logn+1]的上取整,所示时间复杂度为O(logn))
class Solution {
public:
    // 堆排序, 参数i表示开始调整的节点,len表示调整的范围
    void heapify(vector<int>& nums, int i, int len) {
        // 这里的结点从0开始,不是从1开始,因此左孩子序号是2*i + 1,右孩子序号是2*i+2
        int left = 2 * i + 1;
        int right = 2 * i + 2;
        // 假设当前节点是最大的
        int largest = i;
        // 如果左子节点比当前节点大,更新最大值
        if (left < len && nums[left] > nums[largest]) {
            largest = left;
        }
        // 如果右子节点比当前节点大,更新最大值
        if (right < len && nums[right] > nums[largest]) {
            largest = right;
        }
        // 如果最大值不是当前节点,交换最大值和当前节点,并递归调整
        if (largest != i) {
            swap(nums[i], nums[largest]);
            heapify(nums, largest, len);
        }
    }
    // 构建大顶堆
    void heap_sort(vector<int>& nums) {
        int len = nums.size();
        // 从最后一个非叶子节点开始,依次向前调整
        for (int i = len / 2 - 1; i >= 0; i--) {
            heapify(nums, i, len);
        }
        // 交换堆顶和最后一个元素,再调整堆
        for (int i = len - 1; i > 0; i--) {
            swap(nums[0], nums[i]);
            heapify(nums, 0, i);
        }
    }
    
    int findKthLargest(vector<int>& nums, int k) {
        heap_sort(nums);
        return nums[nums.size() - k];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值