今天在学习方法相关知识时,遇到了一些关于递归的知识。后来回家有一道题是关于递归的。题如下:
某工厂生产轿车,一月份生产15000辆,2月份产量是1月份产量减去3000,再翻一番;3月份产量是2月份产量减去3000再翻一番;按这样规律,编写一程序求出该年一共生产多少辆轿车.
很是纠结了一番,因为递归要求有很强的逻辑思维,而我大学中其实我们学习递归的时间是很长的,不管是算法还是以前的图,反正陆陆续续的学了很久。可是自己对递归可以说还是一窍不通。因为一直没有理解递归的精髓,一直只是死板的记公式,比如今天遇到的这道题。就完全没有思路,
后来在网上找到了两种递归方法:
法一:
public class Text3 {
public static void main(String[] args) {
long s=new Text3().Turnout(12);
System.out.println("一年的产量为:"+s);
}
public long Car(int n){
if(n==1){
return 15000;
}else{
return (Car(n-1)-3000)*2;
}
}
public long Turnout(int n){
long a=0;
for(;n>=1;n--){
a += Car(n);
}
return a;
}
}
法二:
package com.lovo;
import java.io.File;
//某工厂生产轿车,一月份生产15000辆,2月份产量是1月份产量减去3000,再翻一番;
//3月份产量是2月份产量减去3000再翻一番;按这样规律,编写一程序求出该年一共生产//多少辆轿车.
public class Tcars {
static int count = 15000;
public static void main(String[] args) {
// TODO 自动生成方法存根
int cars = 15000;
System.out.println("第1个月生产:"+cars);
int moth =1;
dirTree( cars , moth);
System.out.println("全年生产汽车总数:"+count);
}
public static void dirTree(int cars,int moth){
int temp = 0;
if(moth<12){
temp = (cars-3000)*2;
count+= temp;
moth++;
System.out.println("第"+moth+"个月生产:"+temp);
dirTree(temp, moth);
}
}
}
这两位的方法似乎都能实现这道题,但是个人还是比较偏同于第一位的算法。
我们来看看递归算法的要求:
递归算法所体现的“重复”一般有三个要求:
1. 一是每次调用在规模上都有所缩小(通常是减半);
2. 二是相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入);
3. 三是在问题的规模极小时必须用直接给出解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),无条件递归调用将会成为死循环而不能正常结束。
第一位利用月份的逐渐减小,当月份为1时退出,体现了1的要求有所缩小。而返回方法则是相邻两月的关系,总体给人思路很清楚。
而通过他的方法,我也看到了自己思路的误区,
其一是:自己一直是试图只利用一个递归方法就返回总产量。所以就一直卡在如何找出递归公式的误区中。其实,如果只看每月产量的关系的话,其实很容易就看出了月产量之间的递归关系。
其二是:试图使用产量作为参数,其实现在反过来想想。这和递归的三个要求的第一个“每次调用在规模上都有所缩小”就相冲突。
总之通过今天的这道题,看出了自己在逻辑思维上的欠缺和对递归方法精髓的了解还很欠缺。希望以后能逐步补上!