MST

星途 面试题库

面试题:C++递归函数复杂度分析之复杂嵌套递归

给出如下C++递归函数: ```cpp int complexRecursion(int n) { if (n <= 1) { return n; } return complexRecursion(n - 1)+complexRecursion(n - 2)+complexRecursion(n - 3); } ``` 请精确分析该递归函数的时间复杂度,要求使用主定理(Master Theorem)或其他合适的方法,并详细说明分析过程。同时,提出一种优化方案,将该递归函数的时间复杂度降低,并分析优化后函数的时间复杂度。
41.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

时间复杂度分析

  1. 不使用主定理分析

    • 对于函数complexRecursion(int n),当n > 1时,每次调用会产生三个递归调用,分别是complexRecursion(n - 1)complexRecursion(n - 2)complexRecursion(n - 3)
    • T(n)为计算complexRecursion(n)所需的时间。
    • n <= 1时,T(n)=O(1),因为直接返回n,只涉及简单的比较和返回操作,时间为常数。
    • n > 1时,T(n)=T(n - 1)+T(n - 2)+T(n - 3)+O(1),其中O(1)表示比较n <= 1以及加法操作的时间。
    • 由于这是一个线性递归关系,且递归深度最大为n,每次递归分支数为3,所以时间复杂度为指数级。可以大致估算为O(3^n)。因为在递归树中,每层的节点数是以3的倍数增长,递归深度最大为n
  2. 尝试使用主定理分析

    • 主定理的形式为T(n)=aT(n/b)+f(n),其中a是递归调用的次数,b是每次递归中问题规模的缩小因子,f(n)是每次递归调用之外的工作。
    • 对于我们的函数T(n)=T(n - 1)+T(n - 2)+T(n - 3)+O(1),不符合主定理的标准形式,因为这里不是n/b的形式,而是n - kk = 1,2,3)的形式,所以不能直接应用主定理。

优化方案

  1. 使用动态规划优化
    • 思路:通过保存已经计算过的结果,避免重复计算。
    • 代码如下:
int optimizedComplexRecursion(int n) {
    if (n <= 1) {
        return n;
    }
    int dp[n + 1];
    dp[0]=0;
    dp[1]=1;
    for (int i = 2; i <= n; i++) {
        if (i == 2) {
            dp[i]=dp[i - 1]+dp[i - 2]+0;
        } else {
            dp[i]=dp[i - 1]+dp[i - 2]+dp[i - 3];
        }
    }
    return dp[n];
}
  1. 优化后时间复杂度分析
    • 这里使用了一个大小为n + 1的数组dp来存储中间结果。
    • 初始化dp[0]dp[1]的时间复杂度为O(1)
    • 然后通过一个for循环从i = 2n进行计算,每次循环内的操作时间复杂度为O(1),循环次数为n - 1次。
    • 所以总的时间复杂度为O(n),相比优化前的O(3^n)有了显著的降低。

综上,原递归函数时间复杂度为O(3^n),优化后的动态规划函数时间复杂度为O(n)