1.递归和for循环的区别
1.1 区别
循环能做的事情,递归也能做。但是递归能做的事情,循环不一定可以。
递归操作需要频繁地压栈弹栈,需要消耗大量内存资源,效率较低。
1.2 程序示例
public static void main(String[] args){
int num = 20;
long i1 = System.nanoTime();//纳秒级
int result1 = test1(num);
System.out.println(result1);
long i2 = System.nanoTime();
long i3 = System.nanoTime();
int result2 = test2(num);
System.out.println(result2);
long i4 = System.nanoTime();
long time1 = i2 - i1;
long time2 = i4 - i3;
System.out.println("使用递归所需执行时间:" + time1 + " 使用for循环所需执行时间:" + time2);
}
//使用递归计算斐波那契数列的第n位
public static int test1(int num){
if(num == 1 || num == 2){
return 1;
}
return test1(num - 1) + test1(num - 2);
}
//使用for循环计算斐波那契数列的第n位
public static int test2(int num){
int a = 1;//第n-2位
int b = 1;//第n-1位
int c = 1;//第n位
if(num == 1 || num == 2){
return 1;
}
for(int i = 3; i <= num; i++){
c = a + b;
a = b;
b = c;
}
return c;
}
//输出结果:
//6765
//6765
//使用递归所需执行时间:306800 使用for循环所需执行时间:15300
1.3 总结
输出结果中,两种方式的结果是一样的,但是使用递归所需的执行时间远远超过使用for循环。
这是因为递归操作每次调用方法都需要在JVM栈中压入一个栈帧,多次递归后产生的栈帧数目是极大的,对内存空间产生了很大的要求,并且严重影响了程序执行的效率,所以程序执行的时间会很长,甚至会抛出栈溢出的异常。下图是递归到一定程度时产生栈帧的数目:
总结:当遇到像树的遍历这种能用递归但是不能使用for循环的问题时,就使用递归,但是当递归和for循环都可以解决问题的时候,最好采用for循环。
2.递归相关练习题
1、递归求N的阶乘
2、递归求1+2+3+…+10
3、按顺序打印一个数字的每一位(例如1234 打印出1 2 3 4)
4、写一个递归方法,输入一个非负整数,返回组成它的数字之和
5、声明一个方法接收一个参数,判断传递的参数值在斐波那契数列的第几位上,如果不存在打印 -1 ,如果存在,打印对应的位数。
public class DiGui {
public static void main(String[] args){
System.out.println("第1题:" + jieCheng(10));
System.out.println("第2题:" + jiaHe(10));
System.out.print("第3题:");
printEvery(8848);
System.out.println();
System.out.println("第4题:" + numSum(1234));
System.out.println("第5题:" + feiNum(6765));//6765是第20位
}
public static int jieCheng(int num){
return num == 1 ? 1 : num * jieCheng(num - 1);
}
public static int jiaHe(int num){
return num == 1 ? 1 : num + jiaHe(num - 1);
}
public static void printEvery(int num){
int bi = num % 10;
if(num / 10 == 0){
System.out.print(bi + " ");
return;
}
printEvery(num / 10);
System.out.print(bi + " ");
return;
}
public static int numSum(int num){
if(num / 10 == 0){
return num;
}
return num % 10 + numSum(num / 10);
}
public static int feiNum(int num){
//未考虑输入1;
int a = 1;
int b = 1;
int c = 1;
int count = 2;
while(c <= num){
c = a + b;
a = b;
b = c;
count++;
if(c == num){
return count;
}
}
return -1;
}
}
//输出结果
//第1题:3628800
//第2题:55
//第3题:8 8 4 8
//第4题:10
//第5题:20
6、给出一个整数,判断该数是否为质数
使用pow的时候出现了错误,参数列表写为(num, 1/2),由于整数相除,得到的结果均为num的零次方即1。
public class ZhiShu {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
System.out.println(zhiShu(num));
}
public static boolean zhiShu(int num){
if(num == 1){
return true;
}
for(int i = 2; i <= Math.pow(num, 0.5); i++){
if(num % i == 0){
return true;
}
}
return false;
}
}
如有错误或不足之处,敬请指正。