使用递归计算要打印的东西的数量

Using Recursion to compute the number of something to print

我在学习递归,有一个例子,我解决了写 * 字符一定次数的问题。

例如:如果您要传递数字 3,它应该打印 2^3 颗星,这样它就会打印出 8 颗星。

我应该打印 2 ^ k 次,其中 k 是传递的整数。问题的答案是:

public String printStars(int k) {
    if (k == 0) 
        return "*";
    else 
        return printStars(k - 1) + printStars(k - 1); 
}

我似乎无法理解调用堆栈以及它如何解决问题,我的看法是,当我为 int k 传递 3 时,它会执行 n - 1 3 次,直到它达到基本情况,并且会 return 2 stars to the call before that, and since it takes 3 levels to get that deep, it would print 3 x 2 stars so it would print 6 stars.这很奇怪,因为大多数其他递归对我来说很容易,但这很令人困惑。

只需按照代码完成:

应该清楚,在非基础情况下:

printStars(k).length() == 2 * printStars(k - 1).length()

因为这种情况下的值由

给出
return printStars(k - 1) + printStars(k - 1); 

利用这个观察,我们可以通过归纳法证明:

printStars(k).length() == 2^k

(其中^表示幂,而不是按位异或)

  • 在基本情况下 printStars(0).length() == 2^0
  • 是正确的
  • 假设 printStars(k - 1).length() == 2^(k-1)printStars(k).length() == 2 * printStars(k - 1).length() == 2^k

QED.

我认为查看它的简单方法是展开每个函数调用:

当 k = 3 时,return 语句的计算结果为 printStars(2) + printStars(2)

所以它会首先调用左边的 printStars(2),它的计算结果是:

printStars(1) + printStars(1) + printStars(2)

同样,我们先展开左边的:

printStars(0) + printStars(0) + printStars(1) + printStars(2)

printStars(0) 最终将计算为 "*" 所以我们有

"*" + "*" + printStars(1) + printStars(2) == "**" + printStars(1) + printStars(2).

我们已经看到 printStars(1) == "**" 所以我们有:

"****" + printStars(2)。我们已经知道 printStars(2) 将解决什么问题。

我猜它一定总是 kn

递归如何工作:它跨越一棵树:

每次调用 printStars 都会导致一个 * (2^0) 或两个 * (2^1)。

如果你调用 printStars(4):

递归级别 4 ist != 0 所以它 return 是两个单独调用自身的收缩,每个调用都带有参数 (3)。

递归级别 3 ist != 0 所以它 return 是两个单独调用自身的收缩,每个调用都带有参数 (2)。

递归级别 2 ist != 0 所以它 return 是两个单独调用自身的收缩,每个调用都带有参数 (1)。

递归级别 1 ist != 0 所以它 return 是两个单独调用自身的收缩,每个调用都带有参数 (0)。

递归级别 0 ist == 0 所以每个调用 return 有一个 *.

回到递归级别 1,我们收到两个 * 和 contract 和 return 它们。

回到递归级别 2,我们收到两个 ** 和 contract 和 return 它们。

回到递归级别 3,我们收到两个 **** 和 contract 和 return 它们。

回到递归级别 4,我们收到两个 ******** 和 contract 和 return 它们。

所以调用方收到'***************' 2^4=16 *'s

caller                 |
k=4              /         \            (just call yourself 2 times an return contraction of both calls)
k=3          /     \     /     \        (just call yourself 2 times an return contraction of both calls)
k=2         / \   / \   / \   / \       (just call yourself 2 times an return contraction of both calls)
k=1        /\ /\ /\ /\ /\ /\ /\ /\      (just call yourself 2 times an return contraction of both calls)
k=0        ** ** ** ** ** ** ** **      (just return 2^0 = 1 '*')