【问题标题】:Big-O complexity of a recursive solution递归解决方案的大 O 复杂度
【发布时间】:2015-02-28 14:18:36
【问题描述】:

我有一个简单的递归解决方案如下:

public int countPaths(int x, int y) {

    if(x == 0 && y == 0) {
        return 0;
    } else if(x == 0) {
        return 1;
    } else if(y == 0) {
        return 1;
    } else {
        int count = countPaths(x-1, y);
        count += countPaths(x, y-1);
        return count;
    }
}

这是为了解决书中的以下问题:Cracking the coding interview

想象一个机器人坐在 X x Y 网格的左上角。机器人只能在两个方向上移动:向右和向下。机器人从 (0,0) 到 (X,Y) 有多少条可能的路径?

我正在尝试确定运行时间复杂度,我相信它是 O(x+y)。我通过使用递归树来达到这个目的,例如如果 x=2 和 y=2

这棵树的最大深度是 (x+y),每一步所做的功是一个常数。所以完成的最大工作是 (x+y) * c,因此运行时间复杂度是 O(x+y)

问题 1:我说的对吗?我认为我计算的上限不够紧

问题 2:接下来,如果我要使用记忆化改进运行时间,因此不重复计算子问题,那么 Big-o 描述的运行时间复杂度将如何变化? p>

【问题讨论】:

    标签: java algorithm recursion runtime big-o


    【解决方案1】:

    虽然树的深度确实是 O(x+y),但每一层的节点越来越多,决定复杂性的是节点的数量,而不是树的深度。

    如果你写下运行时的递归关系,你会得到:

    T(0, y) = T(x, 0) = 1
    T(x, y) = T(x-1, y) + T(x, y-1) + 1
    

    如果您忽略第二个等式上的 +1(这只会使运行时更好),您将获得与您的代码首先计算的相同函数,即 choose(x+y, y) .

    对于 x=y,这是中心二项式系数,大约为 4^x/sqrt(pi*x),即使 x 的值适中,也足以使算法无用。

    使用记忆化,您为 x 和 y 的每个值做恒定的工作量,因此复杂度为 O(xy)。

    【讨论】:

    • 如果 OP 意识到它是choose (x+y, x),那么他可以计算(我认为对于 O(x+y))。
    • 你可以用 O(min(x, y)) 比 O(x+y) 更好的算术运算来计算 choose(x+y, x)
    • 感谢您的回答;所以没有记忆的运行时间复杂度是 O(4^x)?
    • 你能解释一下符号choose(x+y, y)是什么意思吗?你指的是n选r(n C r) = n! / ((n-r)! * r!) 符号?
    • @Anonymous - 如果您能在我的回答中验证我对您的解释的解释,我将不胜感激。我对二项式系数的细节有点生疏,所以只是尝试简单地(对于 Big-O 分析而言足够)你的解释。
    【解决方案2】:

    如果您根据评估给定对 (x, y) 的计数所需的加法数量来评估复杂性,您会得到重复率

    A(x,y) = A(x-1,y) + A(x,y-1) + 1,

    A(x,0) = A(0,y) = 0.

    设置A(x,y) = P(x,y) - 1循环变为

    P(x,y) - 1 = P(x-1,y) - 1 + P(x,y-1) - 1 + 1,
    

    P(x,y) = P(x-1,y) + P(x,y-1),
    

    使用P(x,0) = P(0,y) = 1,它给出了经典的帕斯卡三角形,并且

    A(x,y) = (x+y)!/(x!y!) - 1.
    

    您还可以使用递归函数调用的数量,

    C(x,y) = C(x-1,y) + C(x,y-1) + 2,
    

    C(0,y) = C(x,0) = 0

    你会通过设置C(x,y) = 2P(x,y) - 2来解决,得到

    C(x,y)= 2(x+y)!/(x!y!)-2.
    

    关于渐近复杂度,这没有区别。没有比O((x+y)!/x!y!) 更简单的公式了。

    使用 memoization,每次评估(使用 x, y>0)只需添加一次或两次调用,并且假设存储/检索一个值的时间恒定,总复杂度要好得多 O(xy)

    【讨论】:

      【解决方案3】:

      根据@Anonymous 的宝贵输入,我们知道递归关系是:

      T(x, y) = T(x-1, y) + T(x, y-1) + 1
      Abusing (which is ok in Big-O analysis) the notation, let x = y 
      T(x, x) = 2 * T(x-1, x) = 2 * 2 * T(x-2, x) = ... = 2 * ... * 2 * T(0, x)
              = O(2^x)
      

      所以运行时复杂度是

      O(2^n) ;其中 n = max(x, y)

      有了memoization,我明白了,谢谢@Anonymous,应该是O(xy)

      【讨论】:

        猜你喜欢
        • 2021-05-07
        • 1970-01-01
        • 2017-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-10
        相关资源
        最近更新 更多