繁体   English   中英

动态规划算法的时空复杂度

[英]Time and space complexity of dynamic programming algorithm

该算法来自第5版的《破解编码访谈》, 网址为https : //www.geekbooks.me/book/view/cracking-the-coding-interview-5th-edition

一个孩子正在n步的阶梯上奔跑,可以一次跳1步,2步或3步。 实施一种方法来计算孩子可以上楼梯的多少种方式。 算法:

 public static int countWaysDP(int n, int[] map) {
    if (n < 0) {
        return 0;
    } else if (n == 0) {
        return 1;
    } else if (map[n] > -1) {
        return map[n];
    } else {
        map[n] = countWaysDP(n - 1, map) + 
                 countWaysDP(n - 2, map) + 
                 countWaysDP(n - 3, map);
        return map[n];
        }
}

该算法的时间和空间复杂度是多少? 我认为由于使用了记忆,因此存储了结果,因此不会像纯递归方法那样多次计算值。 由于存在对countWaysDP的三个调用,因此时间复杂度为O(3n),这是O(n)的元素。 对于map的大小,空间复杂度将为O(n + n),对于递归调用栈,空间复杂度将为n,对于递归调用堆栈,这也是O(n)的元素。 我的推理正确吗?

谢谢

让我们执行代码:

请注意递归堆栈的表示法。 1.2.3。 装置countWaysDP(n)第二递归 countWaysDP(N-2)第三递归 countWaysDP(N-5)。

Consider n=6

1. countWaysDP(6)
1.1. countWaysDP(5)
1.1.1. countWaysDP(4)
1.1.1.1. countWaysDP(3)
1.1.1.1.1. countWaysDP(2)
1.1.1.1.1.1. countWaysDP(1)

1.1.1.1.1.1.1. countWaysDP(0) //returns 1
1.1.1.1.1.1.2. countWaysDP(-1) //returns 0
1.1.1.1.1.1.3. countWaysDP(-2) //returns 0                        -> map[1] = 1 <-

1.1.1.1.1.2. countWaysDP(0) //return 1
1.1.1.1.1.3. countWaysDP(-1) //return 0                           -> map[2] = 2 <-

1.1.1.1.2. countWaysDP(1) //already claculated, returns map[1]
1.1.1.1.3. countWaysDP(0) //returns 1                             ->map[3] = 4 <-

1.1.1.2. countWaysDP(2) //already present, returns map[2]
1.1.1.3. countWaysDP(1) //already present, returns map[1]         -> map[4] = 7 <-

1.1.2. countWaysDP(3) //already present, returns map[3]
1.1.3. countWaysDP(2) //already present, returns map[2]           -> map[5] = 13 <-

1.2. countWaysDP(4) //already present, returns map[4]
1.3. countWaysDP(3) //already present, returns map[3]             -> map[6] = 24 <-

现在假设involking a method is O(1 )操作。 此示例花费的总时间为:

6 + 3 + (2 + 2 + 2 + 2 + 2) = 19

是的,您对TIME的看法是正确的。 它的3n作为最左侧的递归路径采用O(n),然后所有其他调用均为O(2n)。

递归堆栈将占用O(n),因为最大堆栈深度为n + 3,而您的地图将占用O(n)空间。 所以再次重申, SPACEO(n + n)= O(n)

关于算法:尽管您将结果存储在地图中,但算法每次都会进行3次递归调用,然后才将解决方案插入地图中。 这意味着您不会重复使用中间结果。

为了重用,您需要从n = 1开始,然后进行迭代,直到达到所需的步骤数。 这样,您可以确保将结果重用于所有较小的步骤:

for (int i = 1; i <= n; i++) {
  int current = map[i-1]; // you can make 1 step
  if (i > 1) 
    current += map[i-2]; // you can make 2 steps
  if (i > 2)
    current += map[i-3]; // you can make 3 steps
  map[i] = current;
}
return map[n];

现在来看复杂性:

我们使用一张地图,该地图最后有正好n个条目。 因此,空间复杂度为O(n)。

我们从1到n进行一次迭代以进行计算。 因此,时间复杂度也是O(n)。

使用备忘录的简单解决方案(O(N)时间复杂度和空间复杂度)

public static int countWaysDP(int n, int[] map) {
    map[1] = 1; // when n = 1, answer is 1
    map[2] = 2; // when n = 2, answer is 2, (1+1) and (2)
    map[3] = 4; // (1+1+1), (1+2), (2+1), (3)

    for(int i = 4;i <= n; i++)
    {
        map[i] = map[i-1] + map[i-2] + map[i-3]; 
    }

    return map[n];
}

希望这可以帮助!!!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM