/**
* 循环实现
* @param array
* @return
*/
public int addArarry1(int [] array){
int count= 0;
if(array == null|| array.length<=0){
return count;
}
for(int i=0;i
/**
* 递归实现
* @param array
* @param len
* @return
*/
public int addArray2(int[] array,int len){
if(array == null|| len<=0){
return 0;
}
return array[len-1] + addArray2(array,len-1);
}
从这个简单的示例可以看出,递归实现的代码更加简洁,可阅读性也更强。但为什么在日常开发中,我们经常看到的是第一种循环实现,而非递归实现呢?这可能是因为,读书时期老师说过能用循环尽量不要用递归。这种说法也是有道理的,因为递归调用方法自身 是有额外的开销的。这里以java例,来分析递归。
public int fibonacci1(int n){
if(n<=0){
return 0;
}
if(n==1){
return 1;
}
return fibonacci1(n-1)+fibonacci1(n-2);
}
假设n=10,我们看看这个递归过程中发生了什么:
/**
* 循环实现斐波那契
* @param n
* @return
*/
public long fibonacci2(int n) {
long result=0;
long pre1=0;
long pre2=1;
if(n==0) {
return pre1;
}
if(n==1) {
return pre2;
}
for (int i = 2; i <= n; i++) {
result = pre1+pre2;
//移动指针
pre1 = pre2;
pre2 = result;
}
return result;
}
从循环的实现代码来看,虽然不如递归来得简洁,但缺是该问题的最优实现。
存在就是有道理的,不应该像老师说的尽量不用递归。而是应该根据实际情况,在递归深度不超过1000(我的笔记本在超过3000多时出现栈内存溢出,当然可以通过-Xss适当调大栈内存);并且如果使用递归没有重复计算的情况下,我们就可以优先选择递归。还是那句话,因为递归可以使我们的代码看起来更加优雅。
写这篇博客的目的不是为了批判递归,而是让大家更深入的了解递归,并在适当的时候拥抱递归。