2026/6/10 5:44:28
网站建设
项目流程
域名备案网站要不要关,discuz导入wordpress,北欧风格装修效果图,建设工程概念内容例子1/*** 求整数 n 的阶乘** param n 整数* return n 的阶乘*/public int factorial(int n) {if (n 1) {return 1;}return n * factorial(n - 1);}imageDefinition递归是一个循环结构#xff0c;主要用来处理需要循环执行的任务#xff0c;和For循环类似的代码结构。简单说…例子1/*** 求整数 n 的阶乘** param n 整数* return n 的阶乘*/public int factorial(int n) {if (n 1) {return 1;}return n * factorial(n - 1);}imageDefinition递归是一个循环结构主要用来处理需要循环执行的任务和For循环类似的代码结构。简单说就是函数自己能调用自己。fun factorial(n:Int):Int{if(n 1) return nelse return n*factorial(n-1)}先了解一下内存结构但这个不是必须的。image用图理解imageimage从堆栈的角度理解递归递归的底层就是利用堆栈和指令结构所实现的功能。image缺点从使用堆栈的资源角度来说会比For以及其他循环结构更耗资源。内存开销堆栈每次函数调用都会在栈上分配新的栈帧包含参数、返回地址、局部变量等循环只在当前栈帧内重复执行不需要额外的栈空间上下文切换成本堆栈递归涉及函数调用、返回地址保存、寄存器保存等操作循环简单的跳转指令几乎没有上下文切换开销缓存效率堆栈频繁的函数调用可能导致缓存失效循环代码局部性更好缓存命中率更高和For循环的区别和For循环的区别有很多但我主要想讨论他们对解决问题的思考方式上的差别。这个也是我想让大家理解的第二层含义。如果说递归的第一层含义是自己调用自己。那么递归的第二层含义是上一次的函数输出可以成为下一次函数的输入。案例——阶梯问题我们以爬楼梯问题为例有n阶台阶每次可以爬1或2阶问有多少种不同的方法爬到楼顶这实际上就是求斐波那契数列。递归终止条件当 n1 时只有1种方法爬1阶。当 n2 时有两种方法一次爬2阶或者两次各爬1阶。对于n2的情况考虑第一步有两种选择第一步爬1阶那么剩下的n-1阶台阶有 climb_stairs_recursive(n-1) 种方法。第一步爬2阶那么剩下的n-2阶台阶有 climb_stairs_recursive(n-2) 种方法。因此爬n阶台阶的方法数等于这两种情况的方法数之和即climb_stairs_recursive(n) climb_stairs_recursive(n-1) climb_stairs_recursive(n-2)举个例子n3第一步爬1阶剩下2阶有2种方法爬2阶一次2阶或两次1阶第一步爬2阶剩下1阶有1种方法爬1阶所以总共213种方法。同理n4第一步爬1阶剩下3阶3种方法上面n3的情况第一步爬2阶剩下2阶2种方法n2的情况所以总共325种。想要知道4阶有多少种那么需要先知道3阶有多少种那么想知道3阶有多少种那么就得知道2阶有多少种一直追问到终止条件为止。def climb_stairs_recursive(n):# 基础情况if n 1:return 1 # 只有1种方法走1步if n 2:return 2 # 2种方法1→1 或 2# 递归关系f(n) f(n-1) f(n-2)return climb_stairs_recursive(n-1) climb_stairs_recursive(n-2)为了方便理解加上了打印参数def climb_stairs_recursive(n, depth0):indent * depth # 根据深度缩进显示调用层次print(f{indent}- climb_stairs({n}))# 基础情况if n 1:print(f{indent}- 返回 1 (基础情况: n1))return 1if n 2:print(f{indent}- 返回 2 (基础情况: n2))return 2# 递归调用print(f{indent} 计算 climb_stairs({n - 1}) climb_stairs({n - 2}))left climb_stairs_recursive(n - 1, depth 1)right climb_stairs_recursive(n - 2, depth 1)result left rightprint(f{indent}- 返回 {result} {left} {right})return resultprint(计算 climb_stairs(5):)print(f最终结果: {climb_stairs_recursive(5)})image其实这里会造成重复计算和写法有关相当于开启了两个递归。- climb_stairs(4)计算 climb_stairs(3) climb_stairs(2)- climb_stairs(3)对比for循环的写法# 需要在写代码的时候自己维护状态def climb_stairs_iterative(n):if n 2:return na, b 1, 2for i in range(3, n1):a, b b, a breturn b在台阶问题比如爬楼梯每次可以走1步或2步问n阶台阶有多少种走法中递归和循环都可以实现但各有优劣。递归方式的优点代码直观易于理解递归往往能够直接反映问题的数学定义比如斐波那契数列、爬楼梯问题的递推关系。易于设计和实现对于复杂问题递归可以简化设计过程。但是在台阶问题中递归的缺点也很明显效率低存在重复计算递归层越大重复计算则越多导致指数级的时间复杂度。栈溢出风险当n较大时递归深度过深会导致栈溢出。而循环动态规划方式则通过迭代和保存中间结果避免了重复计算时间复杂度为O(n)空间复杂度可以优化到O(1)。总结在快速原型阶段可以使用递归是实现算法好处是快速验证算法思路更容易修改和调整逻辑方便快速实现。而到了中后期的优化阶段可以考虑把循环结构改成动态规划for循环以节省内存资源。还有递归在直观性和易于实现数学定义是其主要优点但在内存性能上不如循环结构动态规划。如果一个问题在初期就很容易用循环结构想清楚则完全必要使用递归没必要画蛇添足。