关于 selectK 函数的问题。
来源:2-10 和 Select K 相关的三个问题
LanceMai
2020-09-03 17:58:12
在这个函数中,去掉了之前的递归终止条件:if(l >= r) return;
按照现在的逻辑,当 l == r 或者 l > r 时,还是会进入 partition 函数执行一些操作。
当 l == r 时,在 partition 中会进行两次无意义的 swap 交换,这一步是不是没有必要?
当 l > r 时,random.nextInt 甚至会直接报错,只不过好像不会到这一步,原因是什么?
1回答
liuyubobobo
2020-09-03
1)
因为在 arr[l, r] 的范围中,我们肯定能够找到第 k 大的元素(只要初始的 k 是合法的),所以,我们把递归终止条件变成了:
if(k == p) return arr[p];
这个意思就是,如果找到了,就返回这个元素;否则,继续递归地去找。
2)
当 l == r 时,在 partition 中会进行两次无意义的 swap 交换,这一步是不是没有必要?
你可以添加一个 if 语句来判断这种情况,对出现这种情况直接 return。但是要注意,这个 if 判断本身也是耗时的。到底是在所有的 partition 中都对 l 和 r 是否相等进行一次判断?还是在 l == r 的时候进行两次“无意义的交换”,那种性能更好,很难说。
不过,其实,在现代编程环境下,这样的性能考量并不重要。你可以选择你觉得最舒服,最容易理解的方式来实现。
3)
我们的代码不会走到 l > r 的情况。因为递归的过程一直保证了解在区间范围里。或者走到 if(k == p),找到解,或者还没有找到解,其实,去左边找(l, p-1)或者去右边找 (p + 1, r) 一定是合法的区间范围。
继续加油!:)
相似问题