【问题标题】:Recursive stair climbing algorithm递归爬楼梯算法
【发布时间】:2015-10-11 17:56:27
【问题描述】:

我正在尝试将以下算法从递归更改为迭代,但在这样做时遇到了问题。 (书:“破解编码面试。”)

问题:“一个孩子正在跑上 n 步的楼梯,一次可以跳 1、2 或 3 步。实现一种方法来计算孩子可以跑多少次楼梯。”

书的答案(递归):

public static int countWays(int n, int[] map) {

    if (n < 0)
        return 0;
    if (n == 0)
        return 1;
    if (map[n] > -1)
        return map[n];

    map[n] = countWays(n - 1, map) + countWays(n - 2, map) + countWays(n - 3, map);

    return map[n];

}

我的答案(迭代):

public static int countWays(int n, int[] map) {

    for (int i = 1; i <= n; i++) {

        //Problem with writing it this way: index could be negative
        map[i] = map[i - 1] + map[i - 2] + map[i - 3];

    }

    return map[n];

}

我给定答案的一个问题是“map[i - 1] + map[i - 2] + map[i - 3]”这行可能会导致负索引,这会引发错误。

我的代码可能还有其他问题。

有人可以帮忙写这个吗?

【问题讨论】:

  • 对于 Python 中的迭代 O(n) 和 O(log(n)) 解决方案,请参阅this answer。

标签: java algorithm debugging recursion iteration


【解决方案1】:

您使用的迭代方法称为自下而上的动态规划。它不同于带有记忆的自顶向下递归。自下而上的效率更高,因为您避免了与递归相关的堆栈开销。

Steps:
1 -> 1 = 1 way
2 -> 11, 2 = 2 ways
3 -> 111, 12, 21, 3 = 4 ways
4 -> 1111, 112, 121, 211, 22, 31, 31 = 7 ways

解决索引问题的另一种方法是创建一个最小大小为 3 的数组,并从第 3 个索引开始。您使用了更多空间,但它简化了您的代码。

public int countWaysDP(int n) {
    if (n < 0) {
        throw new IllegalArgumentException();
    }
    int[] dp = new int[Math.max(3, n)];
    dp[0] = 1; // 1
    dp[1] = 2; // 11, 2
    dp[2] = 4; // 111, 12, 21, 3
    for (int i = 3; i < n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];    
    }
    return dp[n - 1];
}

希望这对您的培训有所帮助。

【讨论】:

    【解决方案2】:

    将第一个索引的值硬编码为 1,然后将总和的每个项放在其自己的 if 语句中以检查负索引。如果索引为负数,则不要将其包含在总和中。

    或者,您可以硬编码前三个值,然后从 4 开始,不用担心。

    【讨论】:

      【解决方案3】:
      public static int countWays(int n, int[] map) {
      
         if(n == 0 || n==1)
           return 1;
         if(n == 2)
           return 2;
         map[0] = 1;
         map[1] = 1;
         map[2] = 2;
         for (int i = 3; i <= n; i++) {
      
             //Problem with writing it this way: index could be negative
             map[i] = map[i - 1] + map[i - 2] + map[i - 3];
      
         }
      
      return map[n];
      

      }

      【讨论】:

        【解决方案4】:

        由于这显然是一个编程面试问题...我将向您展示一个类似的解决方案来复习In Scala,以帮助您学习基础知识。

        import scala.annotation.tailrec
        
        object Main {
        
        /**
         * Count ways to make change...
         */
         def countChange(money: Int, coins: List[Int]): Int = {
            def reduce(money: Int, coins: List[Int]): Int ={
              if (money == 0) 1
              else if (money < 0 || coins.isEmpty) 0
              else reduce(money - coins.head, coins) + reduce(money, coins.tail)
            }
            reduce(money, coins)
          }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-10-20
          • 2020-08-03
          • 2015-02-22
          • 2014-10-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多