从大小为N的数组中选出第k小的数据

该博客介绍了如何从一个大小为N的数组中选择第k小的元素,通过一种类似于快速排序但不同于其平均时间复杂度为O(NlogN)的方法。算法采用递归策略,每次选取数组一部分并确定一个基准值,根据基准值划分数组,通过减少不必要的操作降低时间复杂度至O(N)。

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

这个是从《编程珠玑(续)》的最后一章看到的,感觉相当的经典,特此mark一下。


话说一拿到这个题目直接想到的是快排之类的O(NlogN)复杂度的算法:即先排好序,再得到。时间复杂度O(NlogN)实际上是每一层的递归对N个数进行了操作,一共是logN层。下面介绍的算法类似于快排,但是和快排又有区别,每一层并不是操作了N个数,而是对其中的部分进行操作(感觉像是类似剪枝的过程),所以降低了时间复杂度。


算法概要:每一次递归对数组的部分(原始数组记为a,low表示此时部分数组的最小下标,high表示此时部分数组的最大下标)进行操作,第一次递归是整个数组。每一次递归都对数组的部分选定一个数(任意选,简单处理可以选第一个数a[low]),然后将a分为两部分,小于a[low]的和大于a[low]的,将a[low]作为边界放在两部分的中间,然后可以得到此时a[low]的下标index。若index==k,结束递归;若index<k,下一次迭代的范围是index+1到high;若index>k,下一次迭代的范围是low到index-1。


分析(平均)时间复杂度:N+N/2+N/4+N/8+......+1<2N,所以时间复杂度为O(N)。


public class Solution {
	
	//返回结果	k代表第k小的数		k从1开始
	public int solve(int[] list,int k){
		k = k-1;
		if( k>=0 && k<=list.length-1 )
			return subSolve(list,0,list.length-1,k);
		else
			return Integer.MIN_VALUE;
	}
	
	//返回查找的结果	i是当前的分界线,j是一直增长的
	public int subSolve(int[] list,int low,int high,int k){
			int i = low+1;
			for(in
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值