我的选择算法出了什么问题?

时间:2011-11-16 08:08:10

标签: java algorithm

enter image description here

所以我花了一个星期的时间,并问我的同行,但我们无法做到正确。我按原样把它翻过来,只是为了透明。我只是想知道我的缺点和错误,并理解为什么这不起作用。我尽我所能,并追查它,但递归越深,我就越困惑。希望有比我更有洞察力的人可以帮助我。

另外,我知道这段代码不是最好的。我正在采取步骤,我只是想在优化它之前让它工作。

我的代码:

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;
}

1 个答案:

答案 0 :(得分:4)

这是unit tests非常有用的问题。首先为insertionSort()partitionForSelect()写下这些内容,当您确定这些内容正确时,select()。对于每种方法,编写几个涵盖不同情况的测试,从非常小的数组开始,然后是一些不同的更大的测试用例。

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

另一件有用的事情是添加asserts来检查invariants和中间结果。