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

Posted

技术标签:

【中文标题】使用递归计算要打印的东西的数量【英文标题】:Using Recursion to compute the number of something to print 【发布时间】:2016-03-15 01:52:17 【问题描述】:

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

例如:如果你要传入数字 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 次,直到它达到基本情况,并且会在此之前的调用中返回 2 颗星,并且由于需要 3 个级别才能达到该深度,因此它将打印 3 x 2 颗星,因此它将打印 6 颗星。这很奇怪,因为大多数其他递归对我来说很容易,但这很令人困惑。

【问题讨论】:

我假设您的意思是 k 而不是 n(反之亦然)。 【参考方案1】:

我猜它一定是kn

递归的工作原理:它跨越一棵树:

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

如果你调用 printStars(4):

递归级别 4 ist != 0 所以它返回两个独立调用的收缩,每个调用都带有参数 (3)。

递归级别 3 ist != 0 因此它返回两个独立调用的收缩,每个调用都带有参数 (2)。

递归级别 2 ist != 0 因此它返回两个独立调用的收缩,每个调用都带有参数 (1)。

递归级别 1 ist != 0 所以它返回两个独立调用的收缩,每个调用都带有参数 (0)。

递归级别 0 ist == 0 因此每次调用都返回一个 *

回到递归级别 1,我们收到两个 * 并签订合同并返回它们。

回到递归级别 2,我们收到两个 ** 并签订合同并返回它们。

回到递归级别 3,我们收到两个 **** 并签订合同并返回它们。

回到递归级别 4,我们收到两个 ******** 并签订合同并返回它们。

所以调用者收到 '***************' 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 '*')

【讨论】:

很棒的图表,感谢您的回复,使过程非常清晰,感谢您的宝贵时间!【参考方案2】:

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

当 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) 会解决什么问题。

【讨论】:

谢谢,我一直在关注它,但忘记了需要将 printStars(#) 的原始调用添加到您递归的内容中。所以我得到的答案是正确的答案——你从最初的电话中得到的。谢谢你这么解释【参考方案3】:

只需按照代码进行操作:

应该清楚的是,在非基本情况下:

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。

【讨论】:

感谢您的解释,非常有帮助!

以上是关于使用递归计算要打印的东西的数量的主要内容,如果未能解决你的问题,请参考以下文章

你如何递归地计算数组中负数的数量(Java)?

递归函数 - 计算元组中偶数的数量

如何使用递归函数计算和打印以下序列的前 N ​​个元素的总和

左神算法第八节课:介绍递归和动态规划(汉诺塔问题;打印字符串的全部子序列含空;打印字符串的全排列,无重复排列;母牛数量;递归栈;数组的最小路径和;数组累加和问题,一定条件下最大值问题(01背包))

什么是使用递归计算根的最佳方法C#

计算数字中位数的递归函数