递归de经典

博客探讨了如何使用递归方法解决整数划分问题,给出了不同情况的递推公式,并强调了解题过程中分类讨论的重要性。通过实例展示了整数如3和6的划分,提醒读者在面对复杂问题时要勇于尝试不同的解题策略。

题目如下

任何正整数n都可以写成n=n1+n2+n3+……+nk;1<=n1,n2,n3,……nk<=n;这被称为整数n的划分。

例如

1.正整数3的划分如下:

3;

2+1;

1+1+1;

2.正整数6的划分如下:

6; 
5+1; 
4+2,4+1+1; 
3+3,3+2+1,3+1+1+1; 
2+2+2,2+2+1+1,2+1+1+1+1; 
1+1+1+1+1+1。

结题目标:

设计一个函数,求出n的划分个数。

首先在拿到题目的时候,我们就应该可以知道:n的m划分是个什么意思,也就是说划分必须满足:1<=n1,n2,n3,……nk<=m;这时我们就可以进行递归的分析了,对于所求未知数n的划分就是求f(n,n);

所以就会有下面的几种情况;

1.当n=1或m=1时,都只有一种划分;

2.当n=m时(不包含1),

   划分中含有m时,有一种划分;

   划分中不含m时,有f(n,m-1)中划分;

  总而言之:f(n,m)=1+f(n,m-1);

4.当n>m时,

   划分中含有m时,即划分的形式是{m,{x1, x2, ..., xi}},则{x1, x2, ..., xi}个数为f(n-m,m);

   划分中不含m时,即划分中的数都比m小,则划分个数为f(n,m-1);

   总而言之:f(n,m) =  f(n-m,m)+f(n,m-1)

5.最后一个情况,当n<m时,f(n,m)= f(n,n)

所以总结下来就只有这几个总的情况;

 f(n, m) =             1;                                         ( n = 1 or m = 1 )

                            f(n, n);                                 ( n < m )

                            1+ f(n, m - 1);                      ( n = m )

                            f(n - m, m) + f(n, m - 1);       ( n > m )

 

其实在拿到这个题目的时候,大家就应该可以想到这个思维方式--分类讨论--这可能也是这份递归为什么能成为经典例题的一个原因吧。其实这题并不能很明显的找到缩小问题规模的入口,反而让你引入了一个过渡的变量,而且如果是按照之前一贯的思维,就可能陷入一个死循环,导致最终不能及时AC,所以,他也提醒我们在拿到题目的时候不要局限于一种两种考虑方式,可以多去尝试,大胆地用自己的想到的方法,可能下一个最快AC就来自你的小脑瓜。

 jsj201 zhong

<think>嗯,用户想了解递归的表达式、示例和用法。首先,我需要回忆递归的基本概念,然后整理常见的递归应用场景和示例。用户可能对递归的理解还比较基础,所以需要从简单例子入手,比如阶乘、斐波那契数列这些经典案例。同时,用户提供的引用里提到了正则表达式中的递归用法、表达式计算和构建递归函数的方法,这些也应该涵盖进去。 首先,递归的定义是什么?递归就是一个函数在定义中调用自身的方法。需要满足两个条件:基线条件和递归条件。基线条件就是终止条件,防止无限递归递归条件则是将问题分解为更小的子问题。 接下来,考虑示例部分。阶乘是最简单的递归例子,n! = n * (n-1)!,基线条件是n=0或1时返回1。然后是斐波那契数列,每个数是前两个数之和,基线条件是n=0返回0,n=1返回1。这两个例子比较基础,适合初学者理解。 再进一步,可以举目录遍历的例子,用户可能对文件系统的递归遍历感兴趣。每个目录中的文件和子目录,递归处理子目录,直到没有子目录为止。这样能展示递归在处理嵌套结构时的优势。 另外,用户提供的引用中有关于括号匹配的递归正则表达式,这个可以作为复杂一点的示例。比如匹配嵌套括号,使用正则表达式中的递归结构,不过这个可能需要解释正则表达式的语法,比如用\g<0>来引用整个表达式,实现递归匹配。这里要注意用户提供的引用[1]和[2]中的例子,确保正确引用。 还有表达式求值的问题,引用[3]和[4]提到如何处理括号内的表达式,递归计算子表达式。比如解析类似(2+(3*4))这样的表达式,需要递归地处理每个括号内的部分,直到最内层。这部分可能需要结合栈或者递归下降解析器的概念,但用户可能需要更简化的例子,比如四则运算的递归实现。 在解释递归用法时,需要分步骤说明如何构建递归函数,比如问题分解、确定输入输出、定义基线条件和递归条件。引用[4]中提到了输入输出的一致性,需要强调这一点,例如阶乘函数的输入是n,输出是n的阶乘,而递归调用时输入是n-1,逐步逼近基线条件。 用户可能还会想知道递归的优缺点,比如栈溢出风险、重复计算问题,以及如何优化,比如尾递归或记忆化技术。虽然用户的问题没有直接提到这些,但作为补充内容可能对理解递归有帮助。 最后,根据用户提供的引用,需要确保在回答中正确引用相关部分。例如,在讲解正则表达式递归时引用[1]和[2],在表达式求值时引用[3]和[4],在构建递归函数时引用[4]。 可能还需要生成相关问题,比如递归的应用场景、优化方法、与迭代的比较,或者如何处理递归中的栈溢出。这些相关问题可以帮助用户进一步学习。 总结下来,回答的结构应该是先定义递归,再分示例(简单到复杂),然后用法步骤,最后优缺点和注意事项。确保每个部分都有清晰的例子和引用标注。</think>### 递归的表达式、示例及用法详解 #### 一、递归的核心思想 递归是通过函数**直接或间接调用自身**来解决问题的方法,需满足两个条件: 1. **基线条件**(终止条件):防止无限递归 2. **递归条件**(递推关系):将问题分解为更小的同类子问题 #### 二、经典递归表达式示例 1. **阶乘计算** 数学表达式: $$n! = \begin{cases} 1 & \text{if } n \leq 1 \\ n \times (n-1)! & \text{if } n > 1 \end{cases}$$ Python实现: ```python def factorial(n): if n <= 1: # 基线条件 return 1 return n * factorial(n-1) # 递归条件 ``` 2. **斐波那契数列** 数学表达式: $$F(n) = \begin{cases} n & \text{if } n \leq 1 \\ F(n-1) + F(n-2) & \text{if } n > 1 \end{cases}$$ 代码实现: ```python def fibonacci(n): if n <= 1: # 基线条件 return n return fibonacci(n-1) + fibonacci(n-2) ``` #### 三、特殊场景的递归用法 1. **嵌套结构解析** - **正则表达式匹配嵌套括号**(引用示例[^1][^2]) 使用递归正则匹配如`(a(bc)de)`的结构: ```perl /\( ( (?>[^()]+) | (\g<0>) )* \)/x ``` 其中`\g<0>`表示递归引用整个表达式模式 - **表达式求值**(引用示例[^3][^4]) 处理`(2 + (3 * 4))`的递归逻辑: ```python def eval_expression(s): if s.isdigit(): # 基线条件 return int(s) if '(' in s: # 递归处理括号内表达式 return eval_expression(s[1:-1]) # 处理运算符... ``` 2. **树形结构遍历** 文件目录遍历示例: ```python def traverse_dir(path): for item in os.listdir(path): full_path = os.path.join(path, item) if os.path.isdir(full_path): traverse_dir(full_path) # 递归处理子目录 else: print(full_path) ``` #### 四、构建递归函数的步骤 1. **问题分解**:将原问题转化为同类子问题 *示例:计算`1+2+...+n`可转化为`n + sum(n-1)`* 2. **输入/输出定义**(引用[^4]) - 输入需包含问题规模标识(如整数n、树节点等) - 输出需与子问题结果类型一致 3. **递归三要素**: ```text 递推公式 → 递归条件 终止条件 → 基线条件 调用链路 → 确保向基线条件收敛 ``` #### 五、注意事项 1. **栈溢出风险**:递归深度过大时需改用迭代或尾递归优化 2. **重复计算问题**:可通过记忆化技术优化(如斐波那契数列的缓存优化) 3. **执行效率**:递归调用会产生额外栈帧开销 #### 六、扩展应用领域 - **分治算法**:归并排序、快速排序 - **动态规划**:背包问题、最短路径 - **语法解析**:编译器语法树构建(引用[^5]) - **图形处理**:分形图形生成 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值