Java 我的选择算法有什么问题?

Java 我的选择算法有什么问题?,java,algorithm,Java,Algorithm,所以我花了一个星期的时间在这上面,并询问了我的同龄人,但我们没能做对。我照原样交了,只是为了透明。我只想知道我的缺点和错误,并理解为什么这不起作用。我尽了最大努力,并对其进行了跟踪,但递归越深,我就越困惑。希望有比我更具洞察力的人能帮助我 而且,我知道这个代码不是最好的。我正在采取一些小步骤,我只是想在优化它之前让它发挥作用 我的代码: public static int select(int[] array, int left, int right, int k) { if( arr

所以我花了一个星期的时间在这上面,并询问了我的同龄人,但我们没能做对。我照原样交了,只是为了透明。我只想知道我的缺点和错误,并理解为什么这不起作用。我尽了最大努力,并对其进行了跟踪,但递归越深,我就越困惑。希望有比我更具洞察力的人能帮助我

而且,我知道这个代码不是最好的。我正在采取一些小步骤,我只是想在优化它之前让它发挥作用

我的代码:

public static int select(int[] array, int left, int right, int k) {

    if( array.length <= 1 ) {
        return array[0];
    }
    double proccessedLength = (right-left)+1; // The part of the array we're working with
    int numberOfGroups = (int) proccessedLength/5;
    if( ((double)proccessedLength%5) > 0 ) {
        numberOfGroups++;
    }
    int numberOfRemainders = (int) (proccessedLength%5);
    int[] mediansOfEachGroup = new int[numberOfGroups];

    // Finds the medians of the input array
    for(int x = 0; x < numberOfGroups; x++ ) {
        if( (numberOfRemainders > 0) && x==(numberOfGroups-1)) { // Last Remainder group
            int[] tempArrayForInsertionSorting = new int[numberOfRemainders]; 
            int start=(int) (left+proccessedLength-numberOfRemainders);
            System.out.println(numberOfRemainders);
            for(int y=0; y < numberOfRemainders; y++ ) {
                tempArrayForInsertionSorting[y] = array[start];
                start++;
            }
            int[] sortedTempArray = insertionSort(tempArrayForInsertionSorting,tempArrayForInsertionSorting.length-1);
            if( numberOfRemainders%2 == 0 ) {
                mediansOfEachGroup[numberOfGroups-1] = sortedTempArray[(numberOfRemainders/2)-1];
            } else {
                mediansOfEachGroup[numberOfGroups-1] = sortedTempArray[(int)numberOfRemainders/3];
            }
        } else { // Groups of 5
            int[] tempArrayForInsertionSorting = new int[5];
            int start=left+(x*5);
            for(int y=0; y < 5; y++ ) {
                tempArrayForInsertionSorting[y] = array[start];
                start++;
            }
            int[] sortedTempArray = insertionSort(tempArrayForInsertionSorting,tempArrayForInsertionSorting.length-1);
            mediansOfEachGroup[x] = sortedTempArray[2];
        }
    }


    int medianOfMedians = select(mediansOfEachGroup, left, mediansOfEachGroup.length-1, (int) mediansOfEachGroup.length/2);

    int[] arrayCopyForPartition = new int[array.length];
    System.arraycopy(array,0,arrayCopyForPartition,0,array.length);
    int positionOfMedianOfMedians = partitionForSelect(arrayCopyForPartition, left, right, medianOfMedians);



    if( positionOfMedianOfMedians == k ) {
        return medianOfMedians;
    } else if( positionOfMedianOfMedians < k ){
        return select( array, left, k+1, positionOfMedianOfMedians);
    } else {
        return select( array, k, right, positionOfMedianOfMedians-k);
    }
}

public static void insertionSort(int array[], int n) {
    for (int x = 1; x < n; x++){
        int y = x;
        int temp = array[x];
        while ( (y > 0 ) && (array[y-1] > temp)){
            array[y] = array[y-1];
            y--;
        }
        array[y] = temp;
    }
}

public static int partitionForSelect(int anArray[], int left, int right, int pivot) {
    int x = pivot;
    int i = left-1; 

    for(int j = left; j < right; j++ ) {
        comparisons++;
        if(anArray[j] <= x) {
             i = i + 1;
             int temp =  anArray[i];
             anArray[i] = anArray[j];
             anArray[j] = temp;
        }

    }


    return i+1;
}
publicstaticint-select(int[]数组,int-left,int-right,int-k){

如果(array.length这是一种非常有用的问题。请首先为
insertionSort()
partitionForSelect()编写它们,并在确定它们正确工作后,为
select()编写它们
。对于每种方法,都要编写几个涵盖不同情况的测试,从非常小的数组开始,然后编写一些不同的更大的测试案例

最重要的好处是,当您在算法中发现问题并修复它时,您将立即知道它是否因其他情况而中断


另一件有帮助的事情是添加检查和中间结果。

我实际上在使用JUnit。我的插入工作正常,分区工作正常。我会再次检查。@Doug:看看是否可以向测试中添加更多的角案例,然后开始测试select()它本身具有非常简单的案例。断言可能也有帮助。我有用于插入、分区和选择的断言。我正在传递插入和分区,但没有选择。我的样本数组大小为10。此外,您的
select
方法非常大且复杂。将其分解为许多简单且命名良好的方法,每个方法都有几个测试证明一个好的开始是将你用注释命名的部分提取到它们自己的方法中。