从数组中选择第i个最小元素

时间:2010-05-20 15:45:12

标签: java algorithm

我有一个分而治之的方法来从数组中找到第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

5 个答案:

答案 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--。此外,不需要搜索枢轴所在的位置。这是pq相遇的地方。


关于命名约定

请关注Java naming conventions

  

类名应该是名词,大小写混合,每个内部单词的首字母大写。方法应该是动词,混合大小写,首字母小写,每个内部单词的首字母大写。

相关问题


关于数组声明

另外,不要养成这样声明数组的习惯:

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)

相关问题