思路:利用快速排序的思想,把数组递归划分成两部分。设划分为x,数组左边是小于等于x,右边大于x。关键在于寻找一个最优的划分,经过 Blum 、 Floyd 、 Pratt 、 Rivest 、 Tarjan五位大牛的研究总结,提出了BFPRT 算法(也就是中位数的中位数算法),利用中位数的中位数算法得到的数作为划分可以实现最优划分--在最差情况下能实现O(n)复杂度。接下来考虑可能出现许多重复的数,假设数组中所有的数全部相同,每次划分之后都是当前区间的右端点,即会退化到O(n^2)复杂度。我也是没处理好重复元素,导致TLE多次。一个比较好的办法就是改写partion算法,设每次划分的标准数为x,将所有的与x相等的元素集中到一起,例如数组a[]={4,4,4,2,1,4,5,6},x=4,划分之后应该是{1,2,4,4,4,4,5,6}。很容易能得到等于x的元素的个数cnt,接下来就是决策的处理:

设当前划分的下标为ind.

如果ind+1==k,直接返回a[ind]

如果ind+1<k,递归进入[ind+1,r)的区间继续寻找答案

接下来就是处理重复元素的关键步骤,如果ind+1>k

可分成两种情况:

1、k位于重复元素[ind+1-cnt+1,ind+1]之中,直接返回a[ind],直接结束程序.

2、k位于所有重复元素之前,则应该丢弃重复元素,递归进入[l,ind-cnt+1)的区间继续寻找答案

当然,这题n<=10^6,直接用sort以O(nlgn)也能过。

AC代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e6+5;
int a[maxn];
int n,k;
inline int findmid(int l,int r){  //中位数的中位数
	if(r-l<=5) return (l+r)/2;
	for(int i=0;i<(r-l)/5;++i){
		sort(a+l+i*5,a+l+i*5+5);
		swap(a[l+i],a[l+i*5+2]);
	}
	return findmid(l,l+(r-l)/5);
}
int partion(int l,int r,int &p){ //改进版partion
	int h=findmid(l,r);
	swap(a[h],a[r-1]);
	p=0;
	int ind=l-1;
	for(int i=l;i<r-1;++i){
		if(a[i]==a[r-1]) ++p;
		if(a[i]<=a[r-1])
			swap(a[++ind],a[i]);
	}
	++p;
	swap(a[++ind],a[r-1]);
	int i=l,j=ind-1;
	while(i<j){
		if(a[i]==a[ind]){
			while(a[j]==a[ind]) --j;
			if(i<j){
				swap(a[i],a[j]);
				--j;
			}
		}
		++i;
	}
	return ind;
}
int solve(int l,int r){
	int p=0;
	int ind=partion(l,r,p);
	if(ind+1==k) return a[ind];
	if(ind+1>k){
		if(ind+1-p+1<=k) return a[ind];
		else return solve(l,ind-p+1);
	}
	if(ind+1<k) return solve(ind+1,r);
}
int main(){
	scanf("%d%d",&n,&k);
	for(int i=0;i<n;++i) scanf("%d",&a[i]);
	printf("%d\n",solve(0,n));
	return 0;
} 

如有不当之处欢迎指出!

求第k小的数 O(n)复杂度的更多相关文章

  1. 求第k小的数

    题目链接:第k个数 题意:求n个数中第k小的数 题解: //由快速排序算法演变而来的快速选择算法 #include<iostream> using namespace std; const ...

  2. *HDU2852 树状数组(求第K小的数)

    KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  3. [LeetCode] 4. Median of Two Sorted Arrays(想法题/求第k小的数)

    传送门 Description There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the m ...

  4. 基于快速排序思想partition查找第K大的数或者第K小的数。

    快速排序 下面是之前实现过的快速排序的代码. function quickSort(a,left,right){ if(left==right)return; let key=partition(a, ...

  5. 最快效率求出乱序数组中第k小的数

    题目:以尽量高的效率求出一个乱序数组中按数值顺序的第k 的元素值 思路:这里很容易想到直接排序然后顺序查找,可以使用效率较高的快排,但是它的时间复杂度是O(nlgn),我们这里可以用一种简便的方法,不 ...

  6. 无序数组求第k大/第k小的数

    根据http://www.cnblogs.com/zhjp11/archive/2010/02/26/1674227.html 博客中所总结的7种解法,我挑了其中的解法3和解法6进行了实现. 解法3: ...

  7. 树状数组求第k小的元素

    int find_kth(int k) { int ans = 0,cnt = 0; for (int i = 20;i >= 0;i--) //这里的20适当的取值,与MAX_VAL有关,一般 ...

  8. [LeetCode] Find K-th Smallest Pair Distance 找第K小的数对儿距离

    Given an integer array, return the k-th smallest distance among all the pairs. The distance of a pai ...

  9. #7 找出数组中第k小的数

    「HW面试题」 [题目] 给定一个整数数组,如何快速地求出该数组中第k小的数.假如数组为[4,0,1,0,2,3],那么第三小的元素是1 [题目分析] 这道题涉及整数列表排序问题,直接使用sort方法 ...

随机推荐

  1. Junit4X系列--hamcrest的使用

    OK,在前面的一系列博客里面,我整理过了Assert类下面常用的断言方法,比如assertEquals等等,但是org.junit.Assert类下还有一个方法也用来断言,而且更加强大.这就是我们这里 ...

  2. Linux指令--more,less

    文章出处:http://www.cnblogs.com/peida/archive/2012/11/05/2754477.html,感谢原作者无私的分享. more命令,功能类似 cat ,cat命令 ...

  3. myeclipse取消js校验

    最近玩一个新的项目,项目里面集成了别的项目,在从SVN上第一次荡下来的时候编译的时候老是校验jq文件,老是被卡主,设置myeclipse环境的时候我已经取消了所有的js校验了,但是还是不行.恼火之余, ...

  4. Sql Server的艺术(三) SQL聚合函数的应用

    SQL提供的聚合函数有求和,最大值,最小值,平均值,计数函数等. 聚合函数及其功能: 函数名称 函数功能 SUM() 返回选取结果集中所有值的总和 MAX() 返回选取结果集中所有值的最大值 MIN( ...

  5. R语言-图形初阶

    在本节中,主要目的是如何使用R语言做出简单的图形 案例1:做出wt和mpg之间的关系 attach(mtcars) plot(wt,mpg) abline(lm(mpg~wt)) title('Reg ...

  6. HDU [P1533]

    二分图带权最小匹配(朴素) 只要换几个不等号的方向就行,不需要变换权值的正负 #include <iostream> #include <cstdio> #include &l ...

  7. BZOJ 4516: [Sdoi2016]生成魔咒 [后缀自动机]

    4516: [Sdoi2016]生成魔咒 题意:询问一个字符串每个前缀有多少不同的子串 做了一下SDOI2016R1D2,题好水啊随便AK 强行开map上SAM 每个状态的贡献就是\(Max(s)-M ...

  8. POJ 1873 The Fortified Forest [凸包 枚举]

    The Fortified Forest Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6400   Accepted: 1 ...

  9. vue2.0使用slot插槽分发内容

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  10. 福建百度seo和推广,关键词排名优化,网络营销推广培训

    福建百度seo和推广,关键词排名优化,网络营销推广培训 福建百度seo和推广,关键词排名优化,网络营销推广培训,那么如何才能够让自己的文章信息被百度收录呢?只要说自己的文章能够被百度收录,那么你的信息 ...