在一个数组中找到第k小的数(线性时间选择)

本文介绍了如何在O(n)的时间复杂度内解决元素选择问题,即在给定数组中找到第k小的元素。讨论了随机化算法RandomizedSelect和中位数的中位数法,这两种方法在最坏情况下都能在线性时间内完成选择任务。通过分治策略和有效的基准元素选择,实现了高效的算法实现。
摘要由CSDN通过智能技术生成

在一个数组中找到第k小的数(线性时间选择)

在这一部分,我们讨论的题目为元素选择问题。这类题目的一般问法为:给定线性序集中n个元素和一个整数k,1 <= K <= n,要求找出这n个元素中第k小的元素,如(1,4,3,2,5)中第一小的元素就是1,第5小的元素就是5,第2小的元素就是2。

在某些特殊情况下,很容易设计出解选择问题的线性时间算法。如:当要选择最大元素或最小元素时,显然可以在O(n)时间完成。如果k <= n/logn,通过堆排序算法可以在O(n + klogn) = O(n)时间内找出第k小元素。当k >= n - n/logn时也一样。

一般的选择问题,特别是中位数的选择问题似乎比最小(大)元素要难。但实际上,从渐近阶的意义上,它们是一样的。也可以在O(n)时间完成。

 

下面我们用两种方法进行求解。

第一种:分治算法RandomizedSelect

思想:调用了随机划分函数RandomizedPartition,所以这个分治算法也是一个随机化的算法。

通过将其划分,我们逐渐可以缩小查找的范围进行查找。

时间复杂度:一般情况下为O(n),最坏情况下,数字有序且找最大的数,则为O(n)

 

代码:

#include<windows.h>

#include<iostream>

#include<assert.h>

#include<time.h>

#include<vector>

#include<limits.h>

using namespace std;

template<class Type>

int Partition(Type *ar,int left,int right)

{

int i = left, j = right;

Type tmp = ar[i];

while(i<j)

{

while(i<j && ar[j] > tmp) --j;

if(i<j) { ar[i] = ar[j];}

while(i<j && ar[i] <= tmp) ++i;

if(i<j) { ar[j] = ar[i];}

}

ar[i] = tmp;

return i;

}



template<class Type>

int RandPartition(Type *ar,int left,int right)

{

//Sleep(800);

srand(time(NULL));

int pos = (rand() % (right - left + 1)) + left;

swap(ar[pos],ar[left]);

return Partition(ar,left,right);

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值