关于循环后的left和j交换问题
来源:2-9 作业:Select K 问题
qq_PCplayer_0
2020-11-18 15:37:06
# 具体遇到的问题
# 报错信息的截图
# 相关课程内容截图
# 尝试过的解决思路和结果
# 粘贴全部相关代码,切记添加代码注释(请勿截图)
public int[] getLeastNumbers(int[] arr, int k) {
if (k == 0) {
return new int[0];
} else if (arr.length <= k) {
return arr;
}
// 原地不断划分数组
partitionArray(arr, 0, arr.length - 1, k);
// 数组的前 k 个数此时就是最小的 k 个数,将其存入结果
int[] res = new int[k];
for (int i = 0; i < k; i++) {
res[i] = arr[i];
}
return res;
}
void partitionArray(int[] arr, int lo, int hi, int k) {
// 做一次 partition 操作
int m = partition(arr, lo, hi);
// 此时数组前 m 个数,就是最小的 m 个数
if (k == m) {
// 正好找到最小的 k(m) 个数
return;
} else if (k < m) {
// 最小的 k 个数一定在前 m 个数中,递归划分
partitionArray(arr, lo, m-1, k);
} else {
// 在右侧数组中寻找最小的 k-m 个数
partitionArray(arr, m+1, hi, k);
}
}
// partition 函数和快速排序中相同,具体可参考快速排序相关的资料
// 代码参考 Sedgewick 的《算法4》
int partition(int[] a, int lo, int hi) {
int i = lo;
int j = hi + 1;
int v = a[lo];
while (true) {
while (a[++i] < v) {
if (i == hi) {
break;
}
}
while (a[--j] > v) {
if (j == lo) {
break;
}
}
if (i >= j) {
break;
}
swap(a, i, j);
}
swap(a, lo, j);
// a[lo .. j-1] <= a[j] <= a[j+1 .. hi]
return j;
}
作者:nettee
链接:https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/tu-jie-top-k-wen-ti-de-liang-chong-jie-fa-you-lie-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我想问下 为什么“swap(a, lo, j);”是lo和J交换而不是和i交换 我看快排里面都是和i交换的
1回答
不要记忆最后应该是和 i 交换还是和 j 交换,而要看具体逻辑是怎样的。i 表示什么 j 表示什么,i 怎么变换 j 怎么变化。同样的一个算法,是可以通过改变变量的定义,写出不一样的具体实现的。
这一点我在下一章讲解二分搜索的时候,举了一个具体的例子,如果你感兴趣,可以先学习一下下一章,尤其是这一小节:https://class.imooc.com/lesson/1583#mid=37748
我的建议是,如果你认为应该和 i 交换,把程序具体改成和 i 交换,实际用一个小数据运行一遍,看看是否正确?如果不正确,通过单步跟踪的方式,具体的看,程序中的每一个变量,在执行过程中,是如何变化的?和你想象的是否一样?为什么会得到错误的结果?你想的逻辑那一步的时候执行有问题?
这是学习算法非常重要的方式,进步就在这个过程中哦。
加油!:)
相似问题
回答 1