问题描述
一只猴子第一天摘下若干桃子,当天吃掉一半后又多吃一个。之后每天它都重复这一行为:吃掉前一天剩余桃子的一半,再多吃一个。到了第10天时,发现只剩下1个桃子。
问:猴子第一天摘了多少个桃子?
解题思路
本题需要通过逆向推导解决。已知第10天剩余1个桃子,可以通过递推公式计算前一天的桃子数:
第n天的桃子数 = (第n+1天的桃子数 + 1) × 2
例如:
-
第10天有1个桃子;
-
第9天有
(1 + 1) × 2 = 4
个; -
第8天有
(4 + 1) × 2 = 10
个; -
以此类推,直到第一天。
递归算法实现
采用递归思想,从第1天递推到第10天,逐步逆向求解。
Java代码:
public class PeachProblem {
public static void main(String[] args) {
System.out.println("第一天摘了 " + calculatePeach(1) + " 个桃子");
}
/**
* 递归计算第n天的桃子数量
* @param n 当前天数
* @return 第n天的桃子总数
*/
public static int calculatePeach(int n) {
if (n == 10) {
return 1; // 第10天只剩1个桃子
} else {
// 递推公式:当前天数桃子数 = 2 × (下一天的桃子数 + 1)
return 2 * calculatePeach(n + 1) + 2;
}
}
}
代码解析
-
递归终止条件:当计算到第10天时,直接返回1。
-
递推公式:
2 * calculatePeach(n + 1) + 2
,等价于逆向推导公式(下一天桃子数 + 1) × 2
。 -
时间复杂度:O(n),递归深度为10层,效率较高。
迭代方法拓展
除了递归,还可以用循环实现:
public static int calculateByLoop() {
int peach = 1; // 第10天的桃子数
for (int day = 9; day >= 1; day--) {
peach = 2 * (peach + 1);
}
return peach;
}
两种方法结果一致,均输出1534,但迭代法空间复杂度更低(O(1))。
验证推导过程
通过表格展示每一天的桃子数量变化:
天数 | 剩余桃子数 | 计算公式 |
---|---|---|
10 | 1 | - |
9 | 4 | (1 + 1) × 2 = 4 |
8 | 10 | (4 + 1) × 2 = 10 |
... | ... | ... |
1 | 1534 | (766 + 1) × 2 = 1534 |
总结
-
逆向思维是解决此类问题的关键,通过已知结果反推初始值。
-
递归和迭代均可实现,递归代码简洁,迭代效率更优。
-
该问题可扩展为“第n天剩余m个桃子”的通用解法,只需调整终止条件。
标签: Java算法
递归与递推
经典编程题
讨论: 你还能用其他方法(如数学公式)解决这个问题吗?欢迎在评论区分享你的思路!