所以我花了一个星期的时间,并问我的同行,但我们无法做到正确。我按原样把它翻过来,只是为了透明。我只是想知道我的缺点和错误,并理解为什么这不起作用。我尽我所能,并追查它,但递归越深,我就越困惑。希望有比我更有洞察力的人可以帮助我。
另外,我知道这段代码不是最好的。我正在采取步骤,我只是想在优化它之前让它工作。
我的代码:
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;
}
答案 0 :(得分:4)
这是unit tests非常有用的问题。首先为insertionSort()
和partitionForSelect()
写下这些内容,当您确定这些内容正确时,select()
。对于每种方法,编写几个涵盖不同情况的测试,从非常小的数组开始,然后是一些不同的更大的测试用例。
最重要的好处是,当您在算法中发现问题并修复它时,您会立即知道它是否会因其他情况而中断。
另一件有用的事情是添加asserts来检查invariants和中间结果。