我有以下分区方法和kthsmallest方法(快速排序的变化),在某些情况下可以使用,但在某些情况下可以提供32767的值。
void swap(int* a, int* b){
int temp = *b;
*b = *a;
*a = temp;
}
int partition(int* arr, int l, int r){
int pivot = arr[r];
int i = l, j=0;
for(j=l; j<=r-1; j++){
if(arr[j] <= pivot){
swap(&arr[i], &arr[j]);
i++;
}
}
swap(&arr[i], &arr[j]);
return i;
}
并且第k个最小的函数如下:-
int kthsmallest(int* arr, int low, int high, int k){
/* low = 0 and high = #elements - 1 */
/* k is in between 1 to high + 1 */
if (k>0 & k<=high-low+1) {
// pos is partitioning index, arr[p] is now at right place
int pos = partition(arr, low, high);
// Separately sort elements before / partition and after partition
if(pos-low == k-1){
return arr[pos];
}
//if position returned is greater than k, recurse left subarray
else if(pos-low > k-1){
return kthsmallest(arr, low, pos-1, k);
}
return kthsmallest(arr, pos+1, high, k-(pos+1));
}
}
但是当我在kthsmallest函数中更改最后一个调用时它即有效
改变: return kthsmallest(arr, pos+1, high, k-(pos+1));
至: return kthsmallest(arr, pos+1, high, k-(pos+1)+low);
我想了解为什么我需要对k-(pos + 1)添加低。因为在我看来,当我们在右边有递归输入的子数组时,大数组中的第k个最小数字归结为k-最后一个分区元素-1,即k-(pos + 1)。
您需low
要这样做,因为当您递归地从一个新数组开始时,low
将成为的参考pos
。因此,新k
值将从low
到进行计算pos
。
也许一个例子会更加明确。
从pos
向左我们已经得到了数组,这就是3个最小的元素中最小的元素。现在,我们将从开始的子数组pos+1
。我们需要得到第六个最小的元素:
请记住,我们正在尝试寻找第六个最小元素的子数组。在这种情况下,我们(pos - low + 1)
在子数组中分离了最小的元素。因此,我们的新方法k
将是:我们做一个新的分区:现在我们超过了最后一个子数组的第4个最小元素,因此我们修剪了最后一部分:我们再次进行分区:
所以我们的电话是17
。
希望能帮助到你。
PD:正如David C. Rankin在评论中所说,您可能应该更改&
为&&
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句