迭代(iterate)与递归(recursion)是解决问题常用的两种方法。
递归指方法在内部调用自身。方法调用的时候,每次调用时要做地址保存,参数传递等。
迭代通过循环来重复执行同一步骤,一般递归都可以转化为迭代来解决。
阶乘的两种实现
求阶乘是一个典型的例子,下面分别用迭代与递归实现。
public class Factorial {
/**
* 递归实现阶乘
*
* @param n
* @return
*/
public static int recursion(int n) {
if (n == 1)
return 1;
return n = n * recursion(n - 1);
}
/**
* 迭代实现阶乘
*
* @param n
* @return
*/
public static int iterate(int n) {
int count = 1;
while (n > 0) {
count *= n;
n--;
}
return count;
}
public static void main(String[] args) {
System.out.println(recursion(10));
System.out.println(iterate(10));
}
}
输出结果:
3628800
3628800
递归的优点在于逻辑清晰,让人一眼就能看出来这是个算阶乘的程序;而迭代采用循环完成,往往使人难以立即理解。
但是递归需要栈来存储方法和局部变量信息,栈的大小是有限的,如果递归过深的话会抛出栈溢出的异常(在其他一些语言如C中,会对尾递归进行优化,但Java并没有对尾递归进行优化)。
最简单的抛出栈溢出的例子如下:
public class StackOverflow {
public static void method() {
method();
}
public static void main(String[] args) {
method();
}
}
此外,由于函数调用,可能会影响程序执行效率,因此建议优先选择迭代。
斐波那契数列
通过递归与迭代计算斐波那契数列:
public class Fibonacci {
/**
* 递归实现斐波那契
*
* @param n
* @return
*/
public static int recursion(int n) {
if (n == 1 || n == 2)
return 1;
return recursion(n - 1) + recursion(n - 2);
}
/**
* 迭代实现斐波那契
*
* @param n
* @return
*/
public static int iterate(int n) {
int result = 0;
int previous = 1;
while (n > 0) {
int temp = result;
result += previous;
previous = temp;
n--;
}
return result;
}
public static void main(String[] args) throws IOException {
System.out.println(recursion(10));
System.out.println(iterate(10));
}
}
输出结果:
55
55
可以理解为递归采用的是自顶向下实现,迭代采用的是自底向上实现。至于采用哪种方式并不能一概而论,最好根据实际情况选择。