我有一个分而治之的方法来从数组中找到第i个最小的元素。这是代码:
public class rand_select{
public static int Rand_partition(int a[], int p, int q, int i) {
//smallest in a[p..q]
if ( p==q) return a[p];
int r=partition (a,p,q);
int k=r-p+1;
if (i==k) return a[r];
if (i<k){
return Rand_partition(a,p,r-1,i);
}
return Rand_partition(a,r-1,q,i-k);
}
public static void main(String[] args) {
int a[]=new int []{6,10,13,15,8,3,2,12};
System.out.println(Rand_partition(a,0,a.length-1,7));
}
public static int partition(int a[],int p,int q) {
int m=a[0];
while (p < q) {
while (p < q && a[p++] < m) {
p++;
}
while (q > p && a[q--] > m) {
q--;
}
int t = a[p];
a[p] = a[q];
a[q] = t;
}
int k=0;
for (int i=0; i < a.length; i++) {
if ( a[i]==m){
k=i;
}
}
return k;
}
}
但是,我在运行时遇到异常:java.lang.ArrayIndexOutOfBoundsException
。
答案 0 :(得分:6)
我能够修复一些错误。这一行是次要的:
return Rand_partition(a,r-1,q,i-k);
^
相反,你想要这个:
return Rand_partition(a,r+1,q,i-k);
^
那是因为您已将a[p..q]
分为以下三个部分:
a[p..r-1], a[r], a[r+1..q]
您的原始代码可以处理a[r]
和a[p..r-1]
案例,但使用a[r+1..q]
代替r-1
。
我还能够纠正和简化partition
:
public static int partition(int a[],int p,int q){
int m=a[p]; // not m[0], you want to partition m[p..q]!!!
while ( p<q){
while (p<q && a[p] <m){ // don't do p++ here!
p++;
}
while (q>p && a[q]>m){ // don't do q-- here!
q--;
}
int t=a[p];
a[p]=a[q];
a[q]=t;
}
return p; // no need to search!!!
}
您的原始代码有无关的p++
和q--
。此外,不需要搜索枢轴所在的位置。这是p
和q
相遇的地方。
类名应该是名词,大小写混合,每个内部单词的首字母大写。方法应该是动词,混合大小写,首字母小写,每个内部单词的首字母大写。
另外,不要养成这样声明数组的习惯:
int x[];
您应该使用类型而不是标识符放置括号:
int[] x;
答案 1 :(得分:3)
假设这不是你需要这样做的功课,并且它不在关键路径中(这可能是猜测),只需对数组进行排序并获取索引i
处的值。
public static getIthSmallest(final int[] myArray, final int i) {
if (i < 0) {
System.err.println("You're going to get an ArrayIndexOutOfBoundsException.");
}
if (i >= myArray.length) {
System.err.println("You're going to get an ArrayIndexOutOfBoundsException.");
}
Arrays.sort(myArray);
return myArray[i];
}
答案 2 :(得分:2)
不知道你的bug是什么(我不喜欢Java :)。
这个问题的简单解决方案(O(n)
平均,O(n^2)
最坏的情况)是将源复制到一个简单的qsort
简单实现,并使其仅在包含的一侧进行递归你关心的位置。它应该是大约5行代码不同,所以应该很容易做到。
如果我很小,则有一个O(n + log(n)*i*log(i))
解决方案:
int FindI(int[] array, int i)
{
int[] tmp = array[0..i].dup; // copy first i elements;
sort(tmp); // sort, low to high
foreach(j in array[i..$]) // loop over the rest
if(j < tmp[0])
{
tmp[0] = j;
sort(tmp);
}
return tmp[0];
}
答案 3 :(得分:1)
您尝试实施的算法称为快速选择。 Here是使用三分之一中值分区策略的工作代码链接。
答案 4 :(得分:0)