一个关于递归的有趣问题

今天研究某团门店数据爬取的时候,利用高德地图地址中心点向东南西北四个方向扩展的时候写了一个递归获取地址的方法,发现了一个很有意思的问题,主要探索的是递归的执行顺序 我们都知道递归的顺序是怎样的,就是先执行完内层的,然后逐个往外递归调用,下面这张图能够形象的解释递归的执行顺序

那么下面这段代码的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 后面的几个问题大家自行测试一下就会发现这两个公式都是准的

Table of Contents