剑指 Offer 40. 最小的k个数(随机选择算法)

本文介绍了随机选择算法,该算法基于快速排序,用于寻找数组中的第k大元素。尽管最坏情况下的时间复杂度为O(n^2),但其平均时间复杂度为O(n)。通过随机化主元的选择,算法提高了效率。文章还提供了算法实现,并指出随机选择算法在处理大规模数据时的实用性。

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

在这里插入图片描述

解法:随机选择算法
随机选择算法建立在快排的基础上。

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
 // 选择主元,进行分区
 int partion(int *arr, int left, int right)
 {
     int temp = arr[left];
     while(left < right)
     {
         while(left < right && arr[right] > temp) right--;
         arr[left] = arr[right];
         while(left < right && arr[left] <= temp) left++;
         arr[right] = arr[left];
     }
     arr[left] = temp;
     return left; // 返回相遇的下标,左边的都比它小,右边的都比它大
 }
 // 交换两整数
 void swap(int *a, int *b)
 {
     int temp = *a;
     *a = *b;
     *b = temp;
 }
 // 随机选择主元
 int randPartion(int *arr, int left, int right)
 {
     int num = 1.0*rand()/RAND_MAX*(right-left)+left;
    swap(&arr[left],&arr[num]);
    return partion(arr, left, right);
 }
 // 返回第k大的坐标
int randSelect(int *arr, int left, int right, int k)
 {
     if(left == right) return left;
     int p = randPartion(arr, left, right);
     int m = p - left + 1; // 区间[left, right]的第m大
     if(k == m) return p; // 找到第k大的坐标p,直接返回
     else if(k < m) 
     {
         return randSelect(arr, left, p-1, k);
     }
     else
     {
        return randSelect(arr, p+1, right, k-m);
     }
 }
int* getLeastNumbers(int* arr, int arrSize, int k, int* returnSize){
    // 处理非法输入
    if(k == 0)
    {
        *returnSize = 0;
        return arr;
    }
    int index = randSelect(arr, 0, arrSize-1, k);
    *returnSize = index + 1;
    return arr;
}

虽然随机选择算法的最坏时间复杂度是 O ( n 2 ) O(n^2) O(n2),但其对任意输入的期望时间复杂度却是 O ( n ) O(n) O(n)。(算法笔记:胡凡)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值