不同人眼中的递归
你眼中的盗梦空间:不停做梦
程序员眼中的盗梦空间
那什么是递归?
自己调用自己,最简单的一个案例就是阶乘的问题
1! = 1 | 2! = 2x1 | 3! = 3x2x1 | => f(n) = n x f(n-1) 【当n=1结束】
递归有三个需要知道
这个递归要做什么?
这个递归怎么结束?
当程序执行到一个方法时,就会开辟一个独立的空间(栈),而且其中变量互不影响
《盗梦空间》场景重现
这个递归要做什么?=> 盗梦空间中做了什么
其实做梦就是一个递归,如果睡觉/下药那么就会做梦
在梦中在睡觉/给下药 那么又做梦,目前是梦中梦
第三层在做梦,就是梦中梦中梦......
用程序可以这么表示
void dream(String sleep) {
dream("做梦 / 下药 / 听音乐 / 猛烈撞击");
}
这样会无限做梦,电影中到第五层之后人的脑子就已经不行了,会烧坏脑子,虽然程序比人脑强上不少,可以循环很多次,但架不住它快啊,烧的比人脑还要快,最终会导致栈溢出,程序停止
所以结束条件就显得十分重要,先来看盗梦中是怎么结束的?
听音乐/收到猛烈撞击 会醒过来,回到上一层梦境中,那么程序就变为了这样
void dream(String sleep) {
if ("听音乐".equals(sleep) || "猛烈撞击".equals(sleep)) {
//返回上一层
return;
}
dream("做梦 / 下药 / 听音乐 / 猛烈撞击");
}
就会开辟一个独立的空间(栈)也好理解,没有做梦空间还怎么做梦?
方法局部的变量是独立的,不会相互影响。总不能第2层做梦会影响第一层的人(当然除了死掉,不过那个算结束条件)
递归场景复现
马踏棋盘问题---一个经典的回溯问题
问题描述
如果给定一个m x n的棋盘,在给定一个马儿棋子的初始位置,按照马走日的规则,如何可以在每个方格只进入一次的情况下,走完整个棋盘。
当然,存在棋盘或者有些起始点不能使马儿走完整个棋盘的情况。
问题解析
马儿在任意一个点,总是会有可走的选择,如果可以走的话,选取一个点走,走不通的话就返回上一步,重新考虑下一个点进行尝试
Java实现
void DFS(int[][] act,int i, int j,int step) {
//将马儿当前位置置为已使用,记录当前步数
act[i][j] = step;
if (step == act.length * act.length) {
//如果达到预定步数,则打印,并退出程序
print(act);
System.exit(0);
}
//得到可以落子的坐标集合
List<Luozi> ls = next(act, i, j);
for (Luozi l : ls) {
//递归调用可用坐标
DFS(act,l.i,l.j,step+1);
}
//如果没有达到预定步数,将此点置为0,进行回溯
if (step < act.length * act.length) {
act[i][j] = 0;
}
}
结果输出
19 8 11 28 17 2
10 27 18 1 12 29
7 20 9 30 3 16
26 31 24 15 34 13
21 6 35 32 23 4
36 25 22 5 14 33
以上只提供了核心方法,如需要,源代码请到git上查看:leidl97/algorithm-src