代码之家  ›  专栏  ›  技术社区  ›  peku33

递归函数中的时间复杂性,其中递归减少了大小

  •  0
  • peku33  · 技术社区  · 10 年前

    我必须估计Solve()的时间复杂度:

    // Those methods and list<Element> Elements belongs to Solver class
    
    void Solver::Solve()
    {
        while(List is not empty)
            Recursive();
    }
    
    void Solver::Recursive(some parameters)
    {
    
        Element WhatCanISolve = WhatCanISolve(some parameters); //O(n) in List size. When called directly from Solve() - will always return valid element. When called by recursion - it may or may not return element
        if(WhatCanISolve == null)
            return;
    
        //We reduce GLOBAL problem size by one.
        List.remove(Element); //This is list, and Element is pointed by iterator, so O(1)
    
        //Some simple O(1) operations
    
    
        //Now we call recursive function twice.
        Recursive(some other parameters 1);
        Recursive(some other parameters 2);
    }
    
    //This function performs search with given parameters
    Element Solver::WhatCanISolve(some parameters)
    {
        //Iterates through whole List, so O(n) in List size
        //Returns first element matching parameters
        //Returns single Element or null
    }
    

    我的第一个想法是应该在O(n^2)附近。

    然后我想到

    T(n) = n + 2T(n-1)
    

    其(根据wolframalpha)扩展为:

    O(2^n)
    

    然而,我认为第二个想法是错误的,因为n在递归调用之间减少了。

    我还用大数据集进行了一些基准测试。以下是结果:

    N       t(N) in ms
    10000   480
    20000   1884
    30000   4500
    40000   8870
    50000   15000
    60000   27000
    70000   44000
    80000   81285
    90000   128000
    100000  204380
    150000  754390
    
    2 回复  |  直到 10 年前
        1
  •  2
  •   e0k    10 年前

    你的算法仍然是O(2 n ),即使它每次减少一项问题的大小。你的差分方程

    T(n)=n+2T(n-1)

    不考虑在每个步骤中删除项目。但是它只删除了一项,所以方程应该是T(n)=n+2T(n-1)-1

    通过使用保存代数 WolframAlpha to solve this 给出解决方案T( n ) = ( c 1. + 4) 2 n -1 - n -2仍然为O(2 n ). 它删除了 一 项,考虑到其他因素(尤其是递归),这不是一个可观的数量。

    我想到的一个类似的例子是 n * n 2D矩阵。假设您只将其用于三角矩阵。即使为每一列删除一行进行处理,迭代每个元素仍然具有复杂性O( n 2. ),这与使用所有元素(即正方形矩阵)的情况相同。

    为了进一步证明,我提供了您自己收集的运行时间数据的图表:

    Plot of your running time data

        2
  •  2
  •   Mikhail Maltsev    10 年前

    时间大概是二次的。如果 WhatCanISolve 返回nullptr,如果列表为空,则所有调用

    Recursive(some other parameters 2);
    

    将在O(1)中完成,因为它们是用空列表运行的。这意味着,正确的公式实际上是

    T(n) = C*n + T(n-1)
    

    这意味着,T(n)=O(n^2),这与我们在图中看到的很好地对应。