LeetCode——数组中的第K个最大元素(快速排序和堆排序实现)

本文介绍了如何使用快速排序和堆排序来解决LeetCode中的第K个最大元素问题。首先,详细阐述了快速排序的实现过程,接着讲解了堆排序的步骤,两者都为寻找数组中的第K大元素提供了有效解决方案。

快速排序实现

// 分区
int partition(vector<int>& array, int left, int right){
    // 选择最右的元素作为基准值
    int povit = array[right];
    int i = left, j = right - 1;
    while (i <= j){
        if (array[i] <= povit){
            i++;
        }
        else if (array[j] > povit){
            j--;
        }
        else{
            swap(array[i], array[j]);
        }
    }
    swap(array[i], array[right]);

    return i;
}

int findKthLargest(vector<int>& nums, int k) {
    // 使用快速排序思想

    // 计算第K大元素在升序数组中的索引
    int targetIndex = nums.size() - k;

    int left = 0, right = nums.size() - 1;
    while(left <= right){
        // 当前基准值索引
        int curIndex = partition(nums, left, right);

        if (curIndex == targetIndex){
            return nums[curIndex];
        }
        else if (curIndex < targetIndex){
            left = curIndex + 1;
        }
        else {
            right = curIndex - 1;
        }
    }
    return 0;
}

堆排序实现

// 调整堆,根元素沿树向下移动,直至其合适位置,first和last分别为堆顶和堆底在数组array中的索引
void moveDown(vector<int>& array, int first, int last){
    // first的左子节点
    int curIndex = first * 2 + 1;
    while(curIndex <= last){
        // 有2子节点,且左节点小于右结点
        if (curIndex < last && array[curIndex] < array[curIndex + 1]){
            // 令当前结点为右子节点
            curIndex++;
        }

        if (array[first] < array[curIndex]){
            swap(array[first], array[curIndex]);
            first = curIndex;
            curIndex = curIndex * 2 + 1;
        }
        else{
            break;
        }
    }
}

// 用数组实现最大堆
void buildHeap(vector<int>& array){
    // 最后一个根节点索引
    int i = (array.size() - 1) / 2;
    while (i >= 0){
        moveDown(array, i, array.size() - 1);
        i--;
    }
}

int findKthLargest(vector<int>& nums, int k) {
    if (k > nums.size()){
        return 0;
    }

    // 使用堆排序思想
    // 实现堆
    buildHeap(nums);

    int first = 0, last = nums.size() - 1;
    while (--k){
        // 删除堆顶
        swap(nums[first], nums[last]);
        last--;
        moveDown(nums, first, last);
    }
    
    return nums[first];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值