缘起于网易的一道算法笔试题,之前对递归算法有一个初步印象。感觉递归好像就是一种迭代的过程。将原问题不断分解为若干个与原问题类似更小的问题,直到小问题已知,也就是找到了递归算法的出口,此时,再讲问题回带得到解的结果。废话不多说,先上题。
题目是这样的:有一只猴子第一天摘了很多桃,觉得很高兴就立刻吃了桃总数的一半,然后觉得没吃饱又吃了3个。猴子感觉这样吃桃会立刻没有,于是就定下一个规矩:每次在奇数天吃剩余桃总数的一半再多加3个,每次在偶数天吃剩余桃的总数的一半再多吃一个。请输入一个天数,使得该天数的剩余桃数正好为1,请打印出猴子第一天共摘了多少个桃?
问题分解:设输入的天数为n;
首先,找到问题入口: 第1天时, 求剩余桃数:F(1) ;
其次,找到问题的递归方程,在本题中,递归方程有两个,
若n天为奇数天:有F(n) = (F(n+1)+3)*2
若n天为偶数天:有F(n) = (F(n+1)+1)*2
其中,奇数天与偶数天相互递归。
最后,问题结束:当程序求到第n天时,F(n) = 1 已知。
首先抽取递归式
很明显递归式为,其中day变量用来存放你输入的天数,用于递归结束的标志。在递归中,先判断递归完成后的结果,再写入递归式。
private static int sumOddDay(int day, int count) { //奇数天的递归
if(count == day) return 1;
else return 2*(sumEvenDay(day, count+1) + 3);
}
private static int sumEvenDay(int day, int count) { //偶数天的递归
if(count == day) return 1;
else return 2*(sumOddDay(day,count+1) + 1);
}
补全天数是奇数还是偶数的判断
private static int sumNum(int day, int count){
if(count%2 == 0){
return sumEvenDay(day, count); //偶数天数
}else {
return sumOddDay(day, count); //奇数天数
}
}
最终得到完整程序代码,如下
package Test;
import java.util.Scanner;
public class test {
public static void main(String [] args){
System.out.println("请输入天数:");
Scanner scanner = new Scanner(System.in);
int day = scanner.nextInt(); //输入值
System.out.println(sumNum(day,1));
}
private static int sumNum(int day, int count){
if(count%2 == 0){
return sumEvenDay(day, count); //偶数天数
}else {
return sumOddDay(day, count); //奇数天数
}
}
private static int sumOddDay(int day, int count) {
if(count == day) return 1;
else return 2*(sumEvenDay(day, count+1) + 3);
}
private static int sumEvenDay(int day, int count) {
if(count == day) return 1;
else return 2*(sumOddDay(day,count+1) + 1);
}
}
众所周知,递归算法的需要很大的内存空间,如果本题限制了运行内存,则递归算法不太适用。于是,上网找了有关如何将递归算法转化成循环的方法,先总结如下。
1.使用栈
2.使用循环
大学课上讲的最多的应该就是树的递归算法和非递归算法的转换了吧。楼主也不多说,网上或教科书上都有代码。