使用SuperMemo学习算法的思路
假如现在有一个陌生人朝我走过来,让我写一个使用冒泡排序算法的程序。我没有做任何准备,没有 gpt 可以问,我经过怎样的思维过程可以把这个程序写出来?
我想用 SuperMemo 帮助我把这个思维过程固化下来。
根据 Woz 所述:
derivation steps: in more complex problems to solve, memorizing individual derivation steps is always highly recommended (e.g. solving complex mathematical problems).
推导步骤:在解决更复杂的问题时,总是强烈建议记忆单个推导步骤(例如,解决复杂的数学问题)。
It is not cramming! It is making sure that the brain can always follow the fastest path while solving the problem.
这不是死记硬背!而是确保大脑在解决问题时始终可以遵循最快的路径。
我翻看了一些算法书,没有哪一本教我一步步写代码,往往是一段陈述之后把代码丢过来,然后又是下一段陈述。没有谁告诉我现在做什么、下一步做什么。
我能想到的“固化”路径的的方法,是把自己在写算法程序时的“正确的(理想的)”思考路径记录下来,在 SuperMemo 中对其进行间隔重复。记录时使用“先走一步、再走一步”的形式,便于在 Su 中拆解。
例如,对于“冒泡排序”算法,没有经过“老师”指导,自己凭感觉写出来的“野路子”程序是这样的:
/*
* 实现冒泡排序
* 将元素从小到大排列。
* 思路: 两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。
* */
#include <algorithm>
#include <iostream>
#include <vector>
void Swap(int& i, int& j) {
int temp = i;
i = j;
j = temp;
}
void BubbleSort(std::vector<int> &values) {
while (true) {
// 标志: 是否有元素交换位置
int flag = false;
for (int i = 0; i < values.size() - 1; ++i) {
if (values[i] > values[i + 1]) {
Swap(values[i], values[i+1]);
flag = true;
}
}
// 本轮遍历未发生元素位置交换,所有元素均已在正确位置,结束循环
if (!flag) break;
}
}
int main() {
std::vector<int> values{9, 1, 5, 8, 3, 7, 4, 6, 2};
BubbleSort(values);
std::ranges::for_each(values,
[](int value) { std::cout << value << ' '; });
return 0;
}
我的程序外层循环是一个死循环,内层循环从左到右遍历要排序的序列。而“科班”应该写出的代码则是: 外层进行 n - 1 次循环,暗含程序必然在 n - 1 次遍历之内结束;内层从右到左遍历序列元素,与算法名称“冒泡”契合,小元素逐渐向左移动(气泡“上升到水面”)。
虽然我这次自己“修修改改”、“坑坑洼洼”把代码跑起来了,但是这这个思维过程却不“稳定”,我这次是这样的想法,下次说不定又是另外一种想法,甚至下次无任何头绪。无法总结成一般思维过程的“新想法”注定会消亡。
有自己的想法是好的,但是自己的想法却并不比大家阅读俗成的通行做法更优,那还有什么理由非得自己“另立门户”呢。