目录
2.4 写一个递归方法,输入一个非负整数,返回组成它的数字之和. 例如,输入 1729, 则应该返回 1+7+2+9,它的和是19
1.递归的相关介绍
1.1 故事引例
相信大家都听过一个故事:
从前有坐山,山上有座庙,庙里有个老和尚给小和尚将故事,讲的就是:
"从前有座山,山上有座庙,庙里有个老和尚给小和尚讲故事,讲的就是:
"从前有座山,山上有座庙..."
"从前有座山……"
"
上面的故事有个特征:自身中又包含了自己,因为有些时候,我们遇到的问题直接并不好解决,但是发现将原问题拆分成其子问题之后,子问题与原问题有相同的解法,等子问题解决之后,原问题就迎刃而解了,这也正是递归的思想
1.2 递归的概念
一个方法在执行过程中调用自身, 就称为 "递归"
递归相当于数学上的 "数学归纳法", 有一个起始条件, 然后有一个递推公式.
例如, 我们求 N!
起始条件: N = 1 的时候, N! 为 1. 这个起始条件相当于递归的结束条件.
递归公式: 求 N! , 直接不好求, 可以把问题转换成 N! => N * (N-1)!
递归的必要条件:
1. 将原问题划分成其子问题,注意:子问题必须要与原问题的解法相同
2. 递归出口
1.3 递归执行过程分析
递归的程序的执行过程不太容易理解, 要想理解清楚递归, 必须先理解清楚 "方法的执行过程", 尤其是 "方法执行结束 之后, 回到调用位置继续往下执行"
2.详例
2.1 递归求N的阶乘(详解如何进行递归)
public class Test {
public static void main(String[] args) {
int n = 3;
int ret = fac(n);
System.out.println(ret);//6
}
public static int fac(int n){
if(n == 1){
return 1;
}
return n * fac(n-1);//fac调用函数自身
}
}
递归的详细操作:(用三个图详解)
2.2 按顺序打印一个数字的每一位(1234)
public class Test {
public static void main(String[] args) {
int n = 1234;
num(n);
}
public static void num(int n){
if(n >= 9){
num(n/10);
}
System.out.println(n % 10);
}
}
2.3 递归求1+2+3+4+...+10
public class Test {
public static void main(String[] args) {
int sum = 10;
int ret = sum(10);
System.out.println(ret);
}
public static int sum(int n){
if(n == 1){
return n;
}
else{
return n + sum(n-1);
}
}
}
2.4 写一个递归方法,输入一个非负整数,返回组成它的数字之和. 例如,输入 1729, 则应该返回 1+7+2+9,它的和是19
public class Test {
public static void main(String[] args) {
int n = 1729;
int ret = sum(n);
System.out.println(ret);
}
public static int sum(int num){
if(num < 10){
return num;
}
return num % 10 + sum(num / 10);
}
}
2.5 求斐波那契数列的第 N 项
public class Test {
public static void main(String[] args) {
System.out.println(fib(5));
}
public static int fib(int n){
if(n == 1){
return 0;
}
if(n == 2){
return 1;
}
return fib(n-1) + fib(n-2);
}
}
那么既然递归如此方便,我们就要盲选递归么,当然不是,就拿斐波那契数列来说
看以下代码:
public class Test {
public static int count = 0;
public static void main(String[] args) {
System.out.println(fib(40));
System.out.println(count);
}
public static int fib(int n){
if(n == 1){
return 0;
}
if(n == 2){
return 1;
}
if(n == 3){
count++;
}
return fib(n-1) + fib(n-2);
}
}
如上图运算结果所示当求fib(40)时,count出现了次,出现了冗余运算,此时的执行效率其实并不如循环方法。
那么让我们看看循环方法:
public class Test {
public static void main(String[] args) {
int n = 40;
int ret = fib(n);
System.out.println(ret);
}
public static int fib(int n){
int l1 = 0;
int l2 = 1;
int l3 = 0;
for(int i = 3; i <= n; i++){
l3 = l1 + l2;
l1 = l2;
l2 = l3;
}
return l3;
}
}
所以并不能盲选递归,当数据大的时候,其实循环效率会更高