我正在研究以下问题的解决方案:
描述一种算法,在一个中找到最小的一百万个数字 十亿数字。假设计算机存储器可以容纳所有计算机存储器 十亿数字。
这本书提供了一个选择等级解决方案,但我很难理解它的一些部分:
public static int partition(int[] array, int left, int right, int pivot) {
while (true) {
while (left <= right && array[left] <= pivot) {
left++;
}
while (left <= right && array[right] > pivot) {
right--;
}
if (left > right) {
return left - 1;
}
swap(array, left, right);
}
}
public static int rank(int[] array, int left, int right, int rank) {
int pivot = array[randomIntInRange(left, right)];
int leftEnd = partition(array, left, right, pivot); // returns end of left partition
int leftSize = leftEnd - left + 1;
if (leftSize == rank + 1) {
return max(array, left, leftEnd);
} else if (rank < leftSize) {
return rank(array, left, leftEnd, rank);
} else {
return rank(array, leftEnd + 1, right, rank - leftSize);
}
}
我理解其中的大部分内容,但我不理解以上两行:
if (leftSize == rank + 1) {
return max(array, left, leftEnd);
1。为什么我们返回三个变量的最大值?
2。我们不应该只是返回array[left:leftEnd]
或那种性质的东西吗?
答案 0 :(得分:1)
恭喜您通过仔细研究一本书来学习。这是一项似乎越来越少的关键技能。
如果rank
的返回值的定义是&#34,那么通常会有一般意义:正好有一百万个数字小于或等于rank
。&#34; max
的定义类似于:
int t = array[left];
for (int i = left + 1; i <= leftEnd; i++)
t = Math.max(t, array[i]);
return t;
返回最大值超出了问题陈述,有点奇怪。将元素分区以使最大百万位于顶部会更好,更简单:array[0] through array[999999]
。然后只有在实际需要的时候找到最大值
请注意,因为rank
是尾递归的,所以我认为相同代码的简单迭代版本会更清晰。
我也不相信这段代码是正确的。检查中的leftSize == rank
比leftSize == rank + 1
更有意义。但如果没有更多的定义和调用代码,很难肯定。
答案 1 :(得分:0)
在 Cracking the Coding Interview 6th Edition p中使用相同的等级函数。 569 (除了该行:if (leftSize == rank + 1) {
被修改为rank - 1
)。
提供了最大功能,如下所示:
/* Get largest element in array between left and right indices */
int max(int[] array, int left, int right)
{
int max = Integer.MIN_VALUE;
for(int i = left; i <= right; i++)
{
max = Math.max(array[i], max);
}
return max;
}
至于解释:rank(array, rank)
返回将在排序数组的第i个位置的元素。
leftEnd
是枢轴的位置。如果在pivot元素之前有rank - 1
个元素,则包含所述pivot的rank
个元素。
我相信枢轴始终是最大元素,因此max(array, left, leftEnd);
的调用可以替换为return pivot;