一个关于递归的有趣问题
今天研究某团门店数据爬取的时候,利用高德地图地址中心点向东南西北四个方向扩展的时候写了一个递归获取地址的方法,发现了一个很有意思的问题,主要探索的是递归的执行顺序 我们都知道递归的顺序是怎样的,就是先执行完内层的,然后逐个往外递归调用,下面这张图能够形象的解释递归的执行顺序
那么下面这段代码的out打印的次数大家知道吗?
static int outCount = 0;
private static void test(String d){
if (count>20) {
outCount++;
System.out.println("out/"+d);
return ;
}
count += 4;
System.out.println(count);
System.out.println(d+"E");
test(d+"E");
System.out.println(d+"N");
test(d+"N");
System.out.println(d+"S");
test(d+"S");
System.out.println(d+"W");
test(d+"W");
}
private static int count = 0;
public static void main(String[] args) {
test("");
System.out.println(outCount);
}
Q1 执行了的小伙伴会发现是19次,为什么呢?
Q2 如果把if (count>20) {
改成if (count>=20) {
会是多少次呢?
Q3 如果把20改成24,48,100或者其他的数值呢?
Q4 如果修改count
增长的数值或者下面递归调用自身的数目呢?
其实要解决这些问题并不困难,只要清楚的知道递归的执行顺序就没有问题,剩下的就是注意count
自增长(+4或者+n)与20
(或者其他的数值)比较带来次数的差异就行了。
我们不妨先看一遍执行的结果,因为加了打印所以看起来更直观一点
4
E
8
EE
12
EEE
16
EEEE
20
EEEEE
24
EEEEEE
out/EEEEEE
EEEEEN
out/EEEEEN
EEEEES
out/EEEEES
EEEEEW
out/EEEEEW
EEEEN
out/EEEEN
EEEES
out/EEEES
EEEEW
out/EEEEW
EEEN
out/EEEN
EEES
out/EEES
EEEW
out/EEEW
EEN
out/EEN
EES
out/EES
EEW
out/EEW
EN
out/EN
ES
out/ES
EW
out/EW
N
out/N
S
out/S
W
out/W
19
由于count
是全局的,并且从上面的打印我们就知道递归执行到count
满足>20
的时候,往后递归回来的时候都是会输出out/***
的.
那么假设递归方法体里面调用自己的次数是X
(例子里面是4),count自增的数值是Y
(例子里面是4),循环退出条件是大于M
(例子里面是20)。 那么输出out/***
的次数应该是 X*((M/Y)+1)-(M/Y)
,例子中就是4*((20/4)+1)-(20/4)=19.
如果是>=
的话次数就是(X*(M/Y)-(M/Y))+1
,即(X*((M/Y)-1))+1
,因为当满足>=
的时候都会多打印一次,(4*((20/4)-1))+1=16 后面的几个问题大家自行测试一下就会发现这两个公式都是准的