Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在未排序数组中查找第k个最小元素_Java_Sorting_Partitioning_Pseudocode - Fatal编程技术网

Java 在未排序数组中查找第k个最小元素

Java 在未排序数组中查找第k个最小元素,java,sorting,partitioning,pseudocode,Java,Sorting,Partitioning,Pseudocode,我正在尝试实现以下伪代码。我只需要使用逻辑分区就可以了 Procedure SELECT( k,S) { if |S| =1 then return the single element in S else { choose an element a randomly from S; let S1,S2,and S3 be he sequences of elements in S less than, equal to, and gre

我正在尝试实现以下伪代码。我只需要使用逻辑分区就可以了

Procedure SELECT( k,S) 
{ if  |S| =1 then return the single element in S
   else  { choose an element a randomly from S;
          let S1,S2,and S3 be he sequences of elements in S   
          less than, equal to, and greater than m, respectively;
         if |S1| >=k then return SELECT(k,S1)
          else 
               if (|S1| + |S2| >=k then return m
               else  return SELECT(k-|S1|-|S2| , S3);
         }
}
以下是我迄今为止的尝试:

public static int select(int k, int[] s, int arrayLeft, int arrayRight) {
    if (s.length == 1) {
        return s[0];
    } else {
        Random rand = new Random();
        int right = rand.nextInt(arrayRight) + arrayLeft;
        int m = s[right];
        int pivot = partition(s, arrayLeft, right); // pivot = |s1|
        if (pivot >= k) {
            return select(k, s, arrayLeft, pivot - 1);
        } else {
            // Calculate |s2|
            int s2Length = 0;
            for (int i = pivot; s[i] == m; i++) {
                s2Length++;
            }
            if (pivot + s2Length >= k) {
                return m;
            } else {
                int s3Left = pivot + s2Length;
                return select(k - pivot - s2Length, s, s3Left + 1, s.length);
            }
        }
    }
}

// all elements smaller than m are to the left of it,
// all elements greater than m are to the right of it
private static int partition(int[] s, int left, int right) {
    int m = s[right];
    int i = left;
    for (int j = left; j <= right - 1; j++) {
        if (s[j] <= m) {
            swap(s, i, j);
            i++;
        }
    }
    swap(s, i, right);
    return i;
}

private static void swap(int[] s, int i, int j) {
    int temp = s[i];
    s[i] = s[j];
    s[j] = temp;
}
public static int select(int k,int[]s,int arrayLeft,int arrayRight){
如果(s.length==1){
返回s[0];
}否则{
Random rand=新的Random();
int right=rand.nextInt(arrayRight)+arrayLeft;
int m=s[右];
int pivot=分区(s,arrayLeft,right);//pivot=| s1|
如果(枢轴>=k){
返回选择(k、s、arrayLeft、pivot-1);
}否则{
//计算| s2|
int s2Length=0;
对于(int i=pivot;s[i]==m;i++){
s2Length++;
}
如果(枢轴+s2Length>=k){
返回m;
}否则{
int s3Left=枢轴+s2Length;
返回选择(k-轴-s2Length,s,s3Left+1,s.length);
}
}
}
}
//所有小于m的元素都位于其左侧,
//大于m的所有元素都位于其右侧
私有静态int分区(int[]s,int左,int右){
int m=s[右];
int i=左;

对于(int j=left;j我不确定代码应该如何工作的细节,但我想我已经发现了一些可疑点

首先,我认为您应该准确地说明方法的有效参数,以及它如何使用
arrayLeft
arrayRight
。写一条Javadoc注释并说明这一点。这将使您和其他人更容易就代码中的正确和错误进行争论

这是错误的:

    if (s.length == 1) {
您通过所有递归调用传递相同的数组,因此如果从一开始它就没有长度1(一个小事一桩),它就永远不会有长度1。而是使用<代码> ARARY-Leave和ArayLeale>代码>来确定要考虑的元素的数量。 这一行看起来不对:

        int right = rand.nextInt(arrayRight) + arrayLeft;
如果
arrayLeft
为10,而
arrayRight
12,则可能最多产生21。我曾在下一行观察到
ArrayIndexOutOfBoundsException
,因为
right
指向数组外部

这一行中的注释不正确,可能导致有关代码的错误参数:

        int pivot = partition(s, arrayLeft, right); // pivot = |s1|
partition()
返回的
pivot
是重新排序后
m
的索引。我认为正确的语句是
pivot==arrayLeft+|s1
。请检查您自己

我进一步认为,您不应将
right
作为上述调用中的最后一个参数传递,而应传递
arrayRight
。此错误可能是您观察到
partition()
将任何值保留在
m
右侧的原因

您可能会在以下情况下出现
ArrayIndexOutOfBoundsException

            for (int i = pivot; s[i] == m; i++) {

你应该添加一个额外的条件,比如
i i i'm Middle.在伪代码中,它在哪里说了关于重新排序数组的内容?因为如果你无论如何都要重新排序,你可以使用排序算法,然后返回数组的第k个元素…该算法应该比完全排序更快。你必须重新排序以某种方式呈现S1、S2和S3,通过对数组进行重新排序并不是最愚蠢的事情。您需要学习使用调试器。
select
是否应该通过
arraylight
选择数组索引中的第k个最小元素
arrayLeft
包含?独占?很抱歉,我应该更清楚这一点。当用户首先调用该方法,arrayLeft为0,arrayRight是数组中的最后一个元素。我应该创建另一个方法来调用
select
,这样用户只需要指定k和数组。
                return select(k - pivot - s2Length, s, s3Left + 1, s.length);
                return select(k - pivot - s2Length, s, s3Left, arrayRight);