我想编写一个程序来查找第n个最小的元素,而不使用任何排序技术。
我们可以递归地进行,分割和征服风格,如快速排序吗?
如果没有,怎么样?
答案 0 :(得分:12)
您可以在此处找到有关该问题的信息:Selection algorithm。
答案 1 :(得分:9)
您所指的是选择算法,如前所述。具体来说,您对quicksort的引用表明您正在考虑partition based selection。
以下是它的工作原理:
此算法也适用于查找最高m个元素的排序列表...只需选择第m个最大元素,然后对其上方的列表进行排序。或者,对于速度稍快的算法,请使用Quicksort算法,但拒绝递归到与要查找排序值的区域不重叠的区域。
关于这一点非常巧妙的是它通常在O(n)时间内运行。第一次,它看到整个列表。在第一次递归时,它看到大约一半,然后是四分之一等等。因此,它查看大约2n个元素,因此它在O(n)时间内运行。不幸的是,就像在quicksort中一样,如果你一直选择一个不好的支点,你将在O(n 2 )时间内运行。
答案 2 :(得分:1)
使用heap structure(具体来说,priority queue基于Fibonacci heap,此任务很可能在大约O(n)
时间内完成(n
是列表的长度) {{3}}),O(1)
插入时间和O(log n)
删除时间。
考虑从列表中检索第m个最小元素的任务。通过简单地循环遍历列表并将每个项目添加到优先级队列(大小为m
),您可以在O(n)
时间内有效地创建列表中每个项目的队列(或者可能更少使用一些优化,虽然我不确定这是非常有帮助的)。然后,删除队列中具有最低优先级的元素(最高优先级是最小项目)是一件简单的事情,总共只需要O(log m)
个时间,然后就完成了。
总的来说,算法的时间复杂度为O(n + log n)
,但由于log n << n
(即n
的增长速度比log n
快得多),因此简化为简单O(n)
。在一般情况下,我认为你不会得到比这更有效的东西。
答案 3 :(得分:1)
如果你不想使用斐波那契堆,你可以使用二进制堆。
ALGO:
从数组构造最小二进制堆,此操作将花费O(n)时间。
由于这是一个最小二进制堆,因此根元素是最小值。
所以继续删除元素frm root,直到你得到你的第k个最小值。 o(1)操作
确保在每次删除后重新存储堆kO(logn)操作。
所以这里的运行时间是O(klogn)+ O(n)............所以它是O(klogn)......
答案 4 :(得分:0)
可以像这样使用两个堆栈来定位一次传递中的第N个最小数字。
我普遍同意Noldorins的优化分析
这个堆栈解决方案是朝着一个简单的方案工作(相对更多的数据移动 - 跨越两个堆栈)。堆方案将第N个最小数的提取减少到树遍历(log m
)。
如果您的目标是最佳解决方案(例如,对于大量数字或可能用于编程分配,优化及其演示至关重要),您应该使用堆技术。
通过在K个元素的相同空间内实现两个堆栈(其中K是数据集的大小),可以在空间要求中压缩堆栈解决方案。因此,缺点是插入时额外的堆栈移动。
答案 5 :(得分:0)
Here is the Ans to find Kth smallest element from an array:
#include<stdio.h>
#include<conio.h>
#include<iostream>
using namespace std;
int Nthmin=0,j=0,i;
int GetNthSmall(int numbers[],int NoOfElements,int Nthsmall);
int main()
{
int size;
cout<<"Enter Size of array\n";
cin>>size;
int *arr=(int*)malloc(sizeof(int)*size);
cout<<"\nEnter array elements\n";
for(i=0;i<size;i++)
cin>>*(arr+i);
cout<<"\n";
for(i=0;i<size;i++)
cout<<*(arr+i)<<" ";
cout<<"\n";
int n=sizeof(arr)/sizeof(int);
int result=GetNthSmall(arr,size,3);
printf("Result = %d",result);
getch();
return 0;
}
int GetNthSmall(int numbers[],int NoOfElements,int Nthsmall)
{
int min=numbers[0];
while(j<Nthsmall)
{
Nthmin=numbers[0];
for(i=1;i<NoOfElements;i++)
{
if(j==0)
{
if(numbers[i]<min)
{
min=numbers[i];
}
Nthmin=min;
}
else
{
if(numbers[i]<Nthmin && numbers[i]>min)
Nthmin=numbers[i];
}
}
min=Nthmin;
j++;
}
return Nthmin;
}
答案 6 :(得分:0)
在不使用任何排序方法的情况下在数组中查找第n个最大元素的最简单方法。
public static void kthLargestElement() {
int[] a = { 5, 4, 3, 2, 1, 9, 8 };
int n = 3;
int max = a[0], min = a[0];
for (int i = 0; i < a.length; i++) {
if (a[i] < min) {
min = a[i];
}
if (a[i] > max) {
max = a[i];
}
}
int max1 = max, c = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
if (a[j] > min && a[j] < max) {
max = a[j];
}
}
min = max;
max = max1;
c++;
if (c == (a.length - n)) {
System.out.println(min);
}
}
}