四.递归

1.定义:方法调用自身。递归算法可以缩小规模,递归方法调用自身,但是参数不一样。递归可以用循环(递推,迭代)或者栈来代替

2.递归三要素:边界条件,递归关系式,参数返回值(递归方法,参数不一样)

3.递归算法的时间复杂度

(1)递归算法的时间复杂度= 递归的次数 * 每次递归的时间复杂度

  递归次数和递归深度有关,递归次数就是递归二叉树的节点个数

(2)很多时候,递归可以抽象成一棵二叉树,时间复杂度和二叉树的节点个数有关(递归的次数就是节点的个数)

  满二叉树节点个数:2n-1(n代表层数)第i层有:2i-1个节点

(3)不要一看到递归就想到O(logn)

4.递归算法的空间复杂度

(1)递归算法的空间复杂度 = 递归深度 * 每次递归的空间复杂度

(2)空间复杂度与递归的深度有关:递归深度就是调用栈的深度,就是递归二叉树的深度

 5.递归的每个方法(每次递归)都有自己独立的变量。对于所有递归都操作的同一个变量(共享变量),应该放在递归方法外面。(二叉树递归遍历)

6.经典递归案例:(1)求阶乘(2)求x的n次方(3)斐波那契

7.空间复杂度:O(1),O(n)比较多。在递归的时候,会出现O(logn)的空间复杂度

8.递归方法的归就是迭代方法的迭代

9.递归是用栈实现的

10.递归遍历二叉树是,List<Integer>是共享变量,要放在参数中

1.二分查找

(1)非递归实现

 1     public static int binarySerach(int[] arr,int key) {
 2         int left=0;
 3         int right=arr.length-1;
 4         
 5         while(left<=right) {
 6             int mid=(left+right)/2;
 7             if(key==arr[mid])
 8                 return mid;
 9             if(key<arr[mid])
10                 right=mid-1;
11             if(key>arr[mid]) 
12                 left=mid+1;
13         }
14         return -1;
15     }
View Code

 (2)递归实现

 1     public static int binarySerach(int[] arr,int key,int left,int right) {
 2         int mid=(left+right)/2;
 3         
 4         if(left>right)
 5             return -1;
 6         if(key==arr[mid])
 7             return mid;
 8         
 9         if(key<arr[mid])
10             return binarySerach(arr, key, left, mid-1);
11         
12         if(key>arr[mid])
13             return binarySerach(arr, key, mid+1, right);
14         return -1;
15 
16     }
View Code

 2.汉诺塔问题

1     public static void move(int dish,String from,String temp,String to) {
2         if(dish==1)
3             System.out.println("将盘子"+dish+"从塔座"+from+"移动到目标塔座"+to);
4         else {
5             move(dish-1, from, to, temp);////A为初始塔座,B为目标塔座,C为中介塔座
6             System.out.println("将盘子"+dish+"从塔座"+from+"移动到目标塔座"+to);
7             move(dish-1, temp, from, to);//B为初始塔座,C为目标塔座,A为中介塔座
8         }
9     }
View Code

 3.归并排序

4.消除递归

5.递归的有趣应用

(1)求一个数的乘方

(2)背包问题

(3)组合:选择一支队伍

补充:

1.尾递归:只有递,没有归(或者说:只有归,没有递)。和迭代一样

<think> 我们正在分析关于递归说法的个选项,需要找出错误的说法。以下是每个选项的分析: A. 递归算法的执行过程分递推和回归两个阶段。 - 正确。递归的执行分为两个阶段:递推阶段(不断调用自身直到达到递归出口)和回归阶段(从递归出口开始逐层返回结果)[^1]。 B.递归思想写出的程序往往晦涩难懂。 - 错误。递归代码通常更加简洁清晰,但需要正确理解递归定义、递归拆解和递归出口。递归思想写出的程序往往更符合问题的自然结构,但需要适应递归思维。根据引用[2]提到“递推的思路却和人的思考方式更接近”,但递归代码往往简单清晰明了。因此,这个说法是错误的。 C. 递归调用容易造成堆栈溢出。 - 正确。递归调用使用栈内存,如果递归深度过大,会导致栈溢出[^1][^2]。 D. 递归就是一种程序调用本身的编程技巧。 - 正确。递归的基本定义就是函数直接或间接调用自身。 因此,错误的选项是B。 答案:B §§相关问题§§ 1. 递归和递推在算法设计中的主要区别是什么? 2. 如何避免递归导致的栈溢出问题? 3. 递归算法在哪些经典问题中应用? </think> ### 关于递归说法错误的选项分析 #### 选项解析: 1. **A. 递归算法执行分递推和回归两阶段** - **正确** 递归执行分为: - **递推阶段**:不断调用自身,向递归出口推进 - **回归阶段**:从递归出口逐层返回计算结果 示例:斐波那契数列 `fib(3)` 的执行过程: ```mermaid graph TD A[fib3] --> B[fib2] --> D[fib1] A --> C[fib1] B --> E[fib0] ``` 递推:`fib3→fib2→fib1→fib0` 回归:`fib0+fib1→fib2→fib2+fib1→fib3`[^1][^2] 2. **B. 递归思想写的程序晦涩难懂** - **错误(本题答案)** 递归代码通常更简洁清晰: - 直接映射问题定义(如斐波那契 `fib(n)=fib(n-1)+fib(n-2)`) - 符合分治思想(如树遍历、快速排序) - 引用[2]指出:递归代码"往往简单清晰明了",递推反而更接近人类思考方式[^2] 3. **C. 递归调用易造成堆栈溢出** - **正确** - 每次递归调用消耗栈帧内存 - 深度过大导致栈溢出(如斐波那契`fib(10000)`) - 引用[1]明确警告:"不断递归调用需要很大的栈内存,极其容易造成栈内存溢出"[^1] 4. **D. 递归是程序调用本身的编程技巧** - **正确** - 核心定义:函数直接/间接调用自身 - 必备三要素:递归定义、递归拆解、递归出口(见引用[2]代码示例)[^2] #### 错误选项详解:B - **错误原因**:递归程序通常**更简洁易懂** - 反例:快速排序的递归实现仅需5行,而递推版本需复杂循环控制 - 实际场景:树遍历、分治算法递归可读性显著优于递推 - 对比:递推需手动维护状态(如`prev, curr`变量),递归直接表达逻辑关系 ```python # 递归快速排序 vs 递推快速排序 def quick_sort_recursive(arr): if len(arr) <= 1: return arr # 递归出口 pivot = arr[0] left = quick_sort_recursive([x for x in arr[1:] if x < pivot]) right = quick_sort_recursive([x for x in arr[1:] if x >= pivot]) return left + [pivot] + right # 递归拆解 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值