【递归】(四) 复杂度分析

本文深入探讨了递归的时间和空间复杂度,详细解析了尾递归的概念、优化及其与迭代的比较,同时提供了二叉树最大深度的递归解法,并分析了 Pow(x, n) 的递归解决方案及其潜在问题。" 107155600,8768333,Eclipse PDE:依赖关系可视化与插件分析,"['Eclipse', '插件开发', '依赖管理', '可视化', 'Java']
摘要由CSDN通过智能技术生成

目录

一、递归 —— 时间复杂度

二、递归 —— 空间复杂度

三、尾递归

3.1 基本说明

3.2 其他说明1

3.3 其他说明2

3.4 其他说明3

四、二叉树的最大深度

4.1 题目要求

4.2 解决过程

五、Pow(x, n)

5.1 题目要求

5.2 解决过程

六、Pow(x, n) 多解


一、递归 —— 时间复杂度

参考文献:https://leetcode-cn.com/explore/orignial/card/recursion-i/259/complexity-analysis/1222/


二、递归 —— 空间复杂度

参考文献:https://leetcode-cn.com/explore/orignial/card/recursion-i/259/complexity-analysis/1223/


三、尾递归

3.1 基本说明

# Python implementation
def sum_non_tail_recursion(ls):
    """
    :type ls: List[int]
    :rtype: int, the sum of the input list.
    """
    if len(ls) == 0:
        return 0
    # not a tail recursion because it does some computation after the recursive call returned.
    return ls[0] + sum_non_tail_recursion(ls[1:])


def sum_tail_recursion(ls):
    """
    :type ls: List[int]
    :rtype: int, the sum of the input list.
    """
    def helper(ls, acc):
        if len(ls) == 0:
            return acc
        # this is a tail recursion because the final instruction is a recursive call.
        return helper(ls[1:], ls[0] + acc)
    
    return helper(ls, 0)


3.2 其他说明1

尾递归是一种形式,只是用这种形式表达出的概念可以被某些编译器优化 (如 C、C++ 编译器)。尾递归的特殊形式决定了这种递归代码在执行过程中是可以不需要回溯的 (普通递归都是需要回溯的)。如果编译器针对尾递归形式的递归代码作了这种优化,就可能把原本需要线性复杂度栈内存空间的执行过程用常数复杂度的空间完成。

尾递归优化 (Tail Call Optimization, TCO) 主要是对栈内存空间的优化,这个优化是 O(n) 到 O(1) 的;至于时间的优化,其实是由于对空间的优化导致内存分配的工作减少所产生的,是一个常数优化,不会带来质的变化。

尾递归形式和循环 (或者说"迭代") 形式大致就是同一个逻辑的两种表达形式而已。经过尾递归优化的尾递归代码和循环的代码的执行效率基本上是相当的。这也是 函数式编程效率上没有落后 的一个很重要的原因。

对比不同实现方法的异同 —— 计算斐波那契数列第 n 项 (C++)

// 树形递归 - 最直观的递归实现
int fib_1(int n) {  
    if (n <= 1) {   
        return 1 ;  
    }  
    else {   
        return fib_1(n - 1) + fib_1(n - 2) ;  
    } 
}
// 线形递归 - 一种更高效的递归实现
int fib_2(int n) {  
    int fib_rec(int a , int b , int n) {   
        if (n <= 1) {    
            return 1 ;   
        }   
        else {    
            return a + fib_rec(b , a + b , n - 1)   
        }  
    }  
    return fib_rec(1 , 1 , n) 
}
// 迭代实现 
int fib_3(int n) {  
    int a = 1 , b = 1 ;  
    for(int i = 0 ; i < n ; ++i) {   
        int a_ = b , b_ = a + b ;   
        a = a_ ;   
        b = b_ ;  
    }  
    return a 
}
// 尾递归
int fib_4(int n) {  
    int fib_iter(int a , int b , int n) {   
        if (n == 0) {    
            return a;   
        }   
        else {    
            return fib_iter(b , a + b , n - 1) ;  
            // 尾递归,进入下一个函数不再需要上一个函数的环境了,得出结果以后直接返回。   
        }  
    }  
    return fib_iter(1 , 1 , n) ; 
}

上述 4 例有一定递进关系 (提 fib_1 只为完整,其与另 3 者不是同一类复杂度,可无视之)。尾递归就是把一个依赖上一层环境 (上下文) 的递归 (如 fib_2) 转变为一个不依赖上一层环境的递归 (如 fib_4),从而得到结果后直接返回,而无需层层回溯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值