【问题标题】:Recursion confusion with local variables递归与局部变量混淆
【发布时间】:2017-02-17 09:06:16
【问题描述】:

我正在尝试通过查看示例来提高我的递归技能(阅读书面递归函数)。但是,我可以很容易地得到没有局部变量的递归逻辑。在下面的示例中,我无法理解 total 变量是如何工作的。我应该如何看待使用局部变量来读写的递归函数?我认为它就像堆栈回击。顺便说一句,我写的例子没有变量。我试图只写countThrees(n / 10); 而不是total = total + countThrees(n / 10);,但它不起作用。

带有total 变量:

int countThrees(int n) {
  if (n == 0) { return 0; }
  int lastDigit = n % 10;
  int total = 0;
  total = total + countThrees(n / 10);
  if (lastDigit == 3) {
    total = total + 1;
  }
  return total;
}

简化版

int countThrees(int x)
{
    if (x / 10 == 0) return 0;
    if (x % 10 == 3)
        return 1 + countThrees(x / 10);
    return countThrees(x / 10);
}

【问题讨论】:

    标签: recursion


    【解决方案1】:

    在这两种情况下,确实都必须使用堆栈,但是当有局部变量时,堆栈中需要更多空间,因为您需要将每个局部变量都放入其中。在所有情况下,您跳入新的行号也是存储。

    因此,在您的第二个算法中,如果 x = 13,堆栈将在第一步存储“第 4 行”,在第二个中存储“第 4 行;第 3 行”,在第三步中您不添加堆栈中的任何内容,因为没有新的递归调用。在这一步结束时,您读取堆栈(这是一个先进后出堆栈)以了解您必须去哪里,然后从堆栈中删除“第 3 行”,等等。

    在您的第一个算法中,唯一的区别是您必须在堆栈中添加语言环境变量。所以,在第二步结束时,它看起来像“Total = 0, line 4; Total = 0, line 4”。

    我希望足够清楚。

    【讨论】:

      【解决方案2】:

      第一个条件应该是:

      if (x == 0) return 0;
      

      否则单个 3 会产生 0。

      在函数式风格中,整个代码简化为:

      return x == 0 ? 0
          : countThrees(x / 10) + (x % 10 == 3 ? 1 : 0);
      

      关于局部变量:

      int countThrees(int n) {
          if (n == 0) {
              return 0;
          }
      
          // Let an alter ego do the other digits:
          int total = countThrees(n / 10);
      
          // Do this digit:
          int lastDigit = n % 10;
          if (lastDigit == 3) {
              ++total;
          }
          return total;
      }
      

      原始代码有点不确定,何时或做什么,例如在将其初始化为 0 后添加到总数。

      通过在第一次使用时声明变量,事情变得更加清晰。

      例如绝对懒惰:首先让递归实例计算其他数字的总和,然后自己做最后一个数字。

      只使用一个变量lastDigit并没有错;它解释了正在发生的事情:您检查最后一位数字。

      预增量运算符++x;x += 1;x = x + 1;

      可以反过来做(递归调用和自己的工作),所以它可能说明了作者的心理偏好

      堆栈使用:是的total之前递归调用是堆栈上的一个额外变量。与数字无关。智能编译器也可以看到 total 是一个结果。

      关于变量的使用:它们可以是有状态的,因此对于将递归转化为迭代很有用。对于那个尾递归是最简单的:递归最后发生。

      int countThrees(int n) {
          int total = 0;
          while (n != 0) {
              int digit = n % 10;
              if (digit == 3) {
                  ++total;
              }
              n /= 10; // Divide by 10
          }
          return total;
      }
      

      【讨论】:

      • 感谢您的简化,但您能用本地参数启发我吗? (即总数)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-27
      • 2015-04-27
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多