递归基础例子

小猴子吃苹果,一次吃一半多一个,十天之后剩1个(其实是吃了9天),问第一天有多少苹果。

当我用for循环的时候我发现很简单就可以搞定:前一天就是 x/2-1=1 ——> x=(1+1)*2

public class Monkey {
public static void main(String[] args) {
int sum=1;
for(int i = 1;i<10;i++){
sum=(sum+1)*2;
}
System.out.println(sum);
}

}

 

对于循环我认为是从第十天推第九天然后到第一天的时候有多少苹果。是一个倒推的思想。

当我看了网上的方法是用的递归:

public class monkey {
private static int f(int n){
        if(n == 10){
            return 1;
        }else{
            return 2 * (f(n + 1) + 1);
        }
    }

 

public static void main(String[] args) {

int day=1;
System.out.println(f(day));

}
}

 

而递归则是一个正向的思想,运算还是倒推回来。

就像话螺旋一样,循环是从一点开始想外画,而递归是从外画到最里面的一点。相同的是他们都知道自己的起点终点。

程序的递归好难理解。。背过把。

https://www.bilibili.com/video/av6749471/?p=25(可以看一下)

总结

递归方法:1.已知按剧情发展的最后结果(剩下一个苹果),根据结果确定返回类型(题中是int)

                 2.有一个让递归终止的条件(题中是第十天)

                 3.找出关系表达式,按关系列出来(题中是  当天是(后面一天吃的+1个)的2倍)
---------------------
感谢此博客博主帮我理解了递归!
原文:https://blog.youkuaiyun.com/qq_37752233/article/details/79652621?utm_source=copy

转载于:https://www.cnblogs.com/stitchZsx/p/9779326.html

<think>递归是函数直接或间接调用自身的一种编程技术。它通常用于解决可以被分解为相同问题的子问题的问题。递归函数有两个关键部分:递归基(base case)和递归步骤(recursive step)。递归基是函数不再调用自身的条件,防止无限递归递归步骤则是将问题分解为更小的子问题并调用自身。 在C语言中,递归函数的典型例子包括计算阶乘、斐波那契数列、遍历树结构等。 下面是一个计算阶乘的递归函数示例: ```c #include <stdio.h> // 递归函数计算阶乘 int factorial(int n) { if (n == 0) { // 递归基:0! = 1 return 1; } else { // 递归步骤:n! = n * (n-1)! return n * factorial(n - 1); } } int main() { int number = 5; printf("Factorial of %d is: %d\n", number, factorial(number)); return 0; } ``` **解释:** - 递归基:当`n`等于0时,返回1(因为0的阶乘定义为1)。 - 递归步骤:对于大于0的整数`n`,函数返回`n`乘以`factorial(n-1)`的结果。这样,问题被分解为更小的子问题,直到达到递归基。 另一个经典例子是斐波那契数列: ```c #include <stdio.h> // 递归函数计算斐波那契数列的第n项 int fibonacci(int n) { if (n <= 1) { // 递归基:fib(0)=0, fib(1)=1 return n; } else { // 递归步骤:fib(n) = fib(n-1) + fib(n-2) return fibonacci(n - 1) + fibonacci(n - 2); } } int main() { int n = 10; printf("Fibonacci number at position %d is: %d\n", n, fibonacci(n)); return 0; } ``` **注意:** 斐波那契数列的递归实现效率较低,因为存在大量重复计算。在实际应用中,可以使用动态规划(如迭代法)来优化。 ### 递归的注意事项: 1. **递归基**:必须存在一个或多个递归基,否则会导致无限递归,最终栈溢出(stack overflow)。 2. **栈空间**:递归调用使用栈空间,深度过大的递归可能导致栈溢出。 3. **效率**:递归可能产生重复计算,如斐波那契数列的递归实现。对于复杂问题,考虑使用迭代或记忆化(memoization)优化。 ### 递归与迭代的选择: - 递归通常使代码更简洁,易于理解,尤其适用于问题自然递归的情况(如树遍历)。 - 迭代(循环)通常效率更高,且不消耗栈空间。如果递归深度过大或存在性能问题,应转换为迭代。 §§相关问题§§: 1. 递归和迭代有什么区别? 2. 如何避免递归中的重复计算? 3. 什么是尾递归?C语言中编译器是否支持尾递归优化? 4. 递归函数在内存中是如何存储的? </think>### 递归基础知识和示例 #### 递归的核心概念 递归是函数**直接或间接调用自身**的编程技术,包含两个关键要素: 1. **递归基(Base Case)** 函数不再调用自身的终止条件,防止无限递归 2. **递归步骤(Recursive Step)** 将问题分解为更小的子问题,并调用自身解决 #### 递归的注意事项 - **栈空间消耗**:每次递归调用都会占用栈内存,深度递归可能导致栈溢出 - **效率问题**:某些递归(如朴素斐波那契)存在重复计算,需优化 - **问题适用性**:适合解决分治类问题(树遍历、排序、数学序列等) --- ### 递归示例代码 #### 示例1:阶乘计算(数学递归) ```c #include <stdio.h> int factorial(int n) { // 递归基:0! = 1 if (n == 0) return 1; // 递归步骤:n! = n * (n-1)! else return n * factorial(n - 1); } int main() { printf("5! = %d\n", factorial(5)); // 输出 120 return 0; } ``` **执行流程**: ``` factorial(5) → 5 * factorial(4) → 5 * (4 * factorial(3)) → ... → 5 * 4 * 3 * 2 * 1 * factorial(0) → 5 * 4 * 3 * 2 * 1 * 1 = 120 ``` #### 示例2:斐波那契数列(双递归) ```c #include <stdio.h> int fib(int n) { // 递归基 if (n <= 1) return n; // 递归步骤:fib(n) = fib(n-1) + fib(n-2) return fib(n - 1) + fib(n - 2); } int main() { printf("fib(6) = %d\n", fib(6)); // 输出 8 return 0; } ``` #### 示例3:目录遍历(伪代码演示递归结构) ```c void list_files(DIR *dir) { struct dirent *entry; while ((entry = readdir(dir)) != NULL) { if (entry是目录) { DIR *subdir = opendir(entry->path); list_files(subdir); // 递归处理子目录 closedir(subdir); } else { printf("File: %s\n", entry->name); } } } ``` --- ### 常见递归问题及解决方案 | 问题类型 | 解决方案 | |----------------|------------------------------| | **栈溢出** | 改用迭代或尾递归优化 | | **重复计算** | 使用记忆化(缓存中间结果) | | **无限递归** | 确保递归基一定能被触发 | | **效率低下** | 分析时间复杂度,考虑迭代替代 |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值