快速排除(最优法,不是快排)求随机数组中第k大数(c++)(让数随机没写)

#include <iostream>
using namespace std;
int get_kth(int arr[], int n, int k) {

    int left = 0;
    int right = n - 1;

    while (left < right) {
        while (arr[right] > arr[0] && left < right) {
            right--;
        }
        while (arr[left] <= arr[0] && left < right) {
            left++;
        }
        /**
        *   两个小while结束后会有left < right 仍然成立
        *   所以还会继续进行大的循环
        *   然而,left已经达到我们想要的目的了
        *   所以while(···) right--;一定要写在前替left"挡枪"
        *   在又一次经历了递减后@right == left@ 了
        *   所以left不会在进入while(···) left++;
        *   第二次交换相当于swap(arr[left], arr[left])
        *   这样一来left的值就被确保下来了
        */
        /*//另一种写法
        while (arr[left] <= arr[0] && left + 1 < right) {
            left++;
        }
        while (arr[right] > arr[0] && left < right) {
            right--;
        }
        //这个的推断理由跟上面的差不多

        */
        cout << "前: left = " << left << " right = " << right << " | ";
         for (int i = 0; i < n; ++i) {
            cout << arr[i] << " ";
        }
        cout << endl;
        swap(arr[left], arr[right]);
        cout << "后: left = " << left << " right = " << right << " | ";
        for (int i = 0; i < n; ++i) {
            cout << arr[i] << " ";
        }
        cout << endl;
    }
    swap(arr[0], arr[left]);
    for (int i = 0; i < n; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;
    //此时有left个小于a[0]的且全都排在a[0]前面
    //有n - right 个大于a[0]的,切全都排在最后面(a[0]后面)
    /**
    *   下面的递归与right没有任何关系,
    *   所以只需要保证left"安全"即可
    */
    int _k = left + 1;//检索到小于目标(这里是a[0])的数量
    if (_k == k) {
        return arr[left];//之前的a[0]
    } else if(_k < k) {
        return get_kth(arr + _k, n - _k, k - _k);
    }else if (_k > k){
        return get_kth(arr, left, k);
    }
}

int main() {
    int a[] = {2, 1, 4, 6, 3, 5, 0};
    int b[] = {1, 2, 3, 4, 5, 6, 7};
    int c[] = {4, 1, 3, 7, 2, 5, 6};
    int d[] = {9, 1, 2, 10, 13, 5, 11};
    cout << get_kth(d, 7, 6) << endl;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值