非递归的o(n)的求n个数里面第k大数的算法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了非递归的o(n)的求n个数里面第k大数的算法相关的知识,希望对你有一定的参考价值。

非递归是为了防止栈溢出,因为可能有10000000个数,不要平均时间复杂度为o(n)的算法,要最坏的时间复杂度也是o(n)的算法(所以基于快排思想的求第k大数的算法不要),坐等大牛解答~!
或者直接提供能够求n个数里面的中位数的算法也可~

如果ai范围小,如ai<=10000000,则使用桶排。
否则使用楼上的方法,加入二分思想O(n*logk);
在求中位数时,其实也可以想出O(nlogn),并且O(nlogai)的算法是存在的。
如果是长整型,则O<=310000000,很不错。
参考技术A k如果小的话,另开一个数组sortarray,只保留k个数。
把原来数组里的数一个个加入sortarray,将k+1大的数舍去。
复杂度为k*o(n);追问

这个方法不错。但对于求中位数,复杂度就为O(n^2)了,这个时候有没有更高效的算法?

求一个算法把n个数中的第k大的数求出来,要求时间复杂度为O(n)

rt

int heapsort(int *data1, int n, int bigk)//利用堆排序,存在一种优化方案:建立K大的堆

int data[] = 1,343,34,23,56,234,787,25;
//Part 1
int i, j, j2, k;
int tmp;

for(k = (n>>1) - 1; k >= 0; k--)

tmp = data[k];

for(j = k; (j<<1) <= n-2; j = i)

j2 = j << 1;
if(j2+2 > n-1)
i = j2 + 1;
else

if(data[j2+1] < data[j2+2])
i = j2+2;
else
i = j2+1;


if(tmp < data[i])
data[j] = data[i];
else
break;

data[j] = tmp;


//Part 2
int range = n - bigk;
for(k = n-1; k > range -1; k--)

tmp = data[k];
data[k] = data[0];
for(j = 0; (j<<1) <= k-2; j = i)

j2 = j<<1;
if(j2+2 > k-1)
i = j2+1;
else

if(data[j2+1] < data[j2+2])
i = j2+2;
else
i = j2+1;

if(tmp < data[i])
data[j] = data[i];
else break;

data[j] = tmp;

return data[range];


//堆的方法虽然看起来复杂,却绝对是高效的算法
参考技术A 一楼的太复杂了

建立循环(一个循环是所以数字个数):从第一个数字a开始,和下面每一个数比较,并建立一个识别变量i=0,当有一个数字大于a时i=i+1,当次循环结束时如果i=n-1,这时就求出了这个数跳出循环。剩余的数不需要识别了。
dim a(100) &&假设数组a(100)中包含100个数
int n &&要求的位数
int j,k &&外部循环与内部循环的两上递进变量
int i &&识别变量

for j=1 to 100 step 1
i=0
for k=j+1 to 100 step 1
if a(k)>a(j)
i=i+1
endif
endfor
if i=n-1
exit
endif
endfor

? a(j) &&要求的数

vfp语法
参考技术B 一楼的太复杂了
建立循环(一个循环是所以数字个数):从第一个数字a开始,和下面每一个数比较,并建立一个识别变量i=0,当有一个数字大于a时i=i+1,当次循环结束时如果i=n-1,这时就求出了这个数跳出循环。剩余的数不需要识别了
参考技术C #include <iostream.h>
#include <stdio.h>

void main()

int maxInt=1;
int intArray[6]=1,5,18,2,2,9;
int flags=intArray[0];

for(int i=1; i<=sizeof(intArray)/4;i++)

intArray[i-1]=flags;
if(intArray[i-1]<intArray[i])

flags=intArray[i];
maxInt=i+1;


printf("%d",maxInt);
getchar();
return;


c算法
参考技术D int
heapsort(int
*data1,
int
n,
int
bigk)//利用堆排序,存在一种优化方案:建立K大的堆

int
data[]
=
1,343,34,23,56,234,787,25;
//Part
1
int
i,
j,
j2,
k;
int
tmp;
for(k
=
(n>>1)
-
1;
k
>=
0;
k--)

tmp
=
data[k];
for(j
=
k;
(j<<1)
<=
n-2;
j
=
i)

j2
=
j
<<
1;
if(j2+2
>
n-1)
i
=
j2
+
1;
else

if(data[j2+1]
<
data[j2+2])
i
=
j2+2;
else
i
=
j2+1;

if(tmp
<
data[i])
data[j]
=
data[i];
else
break;

data[j]
=
tmp;

//Part
2
int
range
=
n
-
bigk;
for(k
=
n-1;
k
>
range
-1;
k--)

tmp
=
data[k];
data[k]
=
data[0];
for(j
=
0;
(j<<1)
<=
k-2;
j
=
i)

j2
=
j<<1;
if(j2+2
>
k-1)
i
=
j2+1;
else

if(data[j2+1]
<
data[j2+2])
i
=
j2+2;
else
i
=
j2+1;

if(tmp
<
data[i])
data[j]
=
data[i];
else
break;

data[j]
=
tmp;

return
data[range];

//堆的方法虽然看起来复杂,却绝对是高效的算法

以上是关于非递归的o(n)的求n个数里面第k大数的算法的主要内容,如果未能解决你的问题,请参考以下文章

n阶乘的非递归算法

算法导论中,为啥合并排序的递归树的高度为lgn?

归并排序的递归算法与非递归

斐波那契数列的两种实现(递归和非递归)

面试常见算法

基于邻接表的深度优先遍历 (非递归)