int __partition(int *arr, int l, int r) {
int v = arr[l];
// 保持区间从遍历开始到结束的性质不变 arr[l+1...j] < v ; arr[j+1...i) > v
// 初始时(未开始考察) j [l+1...j] 等价于 [j+1 ... j] 此时区间为空
int j = l;
// 初始时(未开始考察) i [j+1 ... i) 等价于 [j+1 ... j+1) 此时区间为空
int i = l + 1;
while (i <= r) {
if (arr[i] < v) {
j++;
swap(arr[i], arr[j]);
}
i++;
}
// arr[i-1] 为最后一个 >= v 的元素。i此时在数组中已经越界,但程序不会访问。
// arr[j] 为最后一个 < v 的元素。交换后v找到了在目标数组的绝对位置。
swap(arr[j], arr[l]);
return j;
}
老师好!本人写业务代码一年有余,做的web后端。此次已经第三次(跨专业自学、准备面试、准备考研)训练快排的白板写作,发现并不能完全吃透快排,学习算法的路上颇有点吃力不讨好的感觉。我尝试调整我的学习方法,在方法论上有疑问!
当我能看懂视频中的动画演示的时候,我是不是要立刻尝试实现?
目前我的做法是,看完视频后,脑子里会过一遍动画,但是不做机械系记忆。第二天同一时间再进行白板写作。
总是在寻求边界问题的明确语义而花费大量时间,是否值得?如何优化方法?
看视频的时候,实现”保持区间从遍历开始到结束的性质不变“,让我疑惑,也让我写代码的时候异常痛苦。
具体表现在,我实现帖子上的代码的过程:
2.1 如果有1000个数字进行快排,大概能清楚第4~5轮的动画演示。开始写代码,卡在第一个for循环不知道 i
和j
分别取什么值合理,怕一步错步步错。
2.2 再看一遍动画演示,依旧不能自信的写出来,表现为写写删删改改,不运行程序。
2.3 直接看老师的代码,给我的感觉是注释也看不懂,开始怀疑自己的理解能力。
2.4 尝试自言自语去描述快排的过程,很困难,但是无法提出”正确的问题“。
2.5 尝试自己写代码,卡住了也忍住不看老师的代码,这段时间会容易焦虑。
2.6 用了两个晚上约6h,代码写完。已经能理解初始情况 i
和j
的下标取值,并用while
循环改写了老师第一个快排实现。我发现整个算法,最难理解的是开始和结束的边界问题。
2.7 完善自己的注释,再看一遍老师的代码,才明白老师注释背后的逻辑。
2.8 综上,约10h才能让我有自信重新完成快排的白板写作。
登录后可查看更多问答,登录/注册