java递归函数的例子
(1) 递归执行过程
例子:求N!。
这是一个简单的"累乘"问题,用递归算法也能解决。
n! = n * (n - 1)! n > 1
0! = 1, 1! = 1 n = 0,1
因此,递归算法如下:
Java代码
fact(int n) {
if(n == 0 || n == 1)
return 1;
else
return n * fact(n - 1);
}
以n=3为例,看运行过程如下:
fact(3) ----- fact(2) ----- fact(1) ------ fact(2) -----fact(3)
------------------------------> ------------------------------>
递归 回溯
递归算法在运行中不断调用自身降低规模的过程,当规模降为1,即递归到fact(1)时,满足停止条件停止递归,开始回溯(返回调用算法)并计算,从fact(1)=1计算返回到fact(2);计算2*fact(1)=2返回到fact(3);计算3*fact(2)=6,结束递归。
算法的起始模块也是终止模块。
(2) 递归实现机制
每一次递归调用,都用一个特殊的数据结构"栈"记录当前算法的执行状态,特别地设置地址栈,用来记录当前算法的执行位置,以备回溯时正常返回。递归模块的形式参数是普通变量,每次递归调用得到的值都是不同的,他们也是由"栈"来存储。
(3) 递归调用的几种形式
一般递归调用有以下几种形式(其中a1、a2、b1、b2、k1、k2为常数)。
<1> 直接简单递归调用: f(n) {...a1 * f((n - k1) / b1); ...};
<2> 直接复杂递归调用: f(n) {...a1 * f((n - k1) / b1); a2 * f((n - k2) / b2); ...};
<3> 间接递归调用: f(n) {...a1 * f((n - k1) / b1); ...},
g(n) {...a2 * f((n - k2) / b2); ...}。
2. 递归算法效率分析方法
递归算法的分析方法比较多,最常用的便是迭代法。
迭代法的基本步骤是先将递归算法简化为对应的递归方程,然后通过反复迭代,将递归方程的右端变换成一个级数,最后求级数的和,再估计和的渐进阶。
<1> 例:n!
算法的递归方程为: T(n) = T(n - 1) O(1);
迭代展开: T(n) = T(n - 1) O(1)
= T(n - 2) O(1) O(1)
= T(n - 3) O(1) O(1) O(1)
= ......
= O(1) ... O(1) O(1) O(1)
= n * O(1)
= O(n)
这个例子的时间复杂性是线性的。
<2> 例:如下递归方程:
T(n) = 2T(n/2) 2, 且假设n=2的k次方。
T(n) = 2T(n/2) 2
= 2(2T(n/2*2) 2) 2
= 4T(n/2*2) 4 2
= 4(2T(n/2*2*2) 2) 4 2
= 2*2*2T(n/2*2*2) 8 4 2
= ...
= 2的(k-1)次方 * T(n/2的(i-1)次方) $(i:1~(k-1))2的i次方
= 2的(k-1)次方 (2的k次方) - 2
= (3/2) * (2的k次方) - 2
= (3/2) * n - 2
= O(n)
这个例子的时间复杂性也是线性的。
<3> 例:如下递归方程:
T(n) = 2T(n/2) O(n), 且假设n=2的k次方。
T(n) = 2T(n/2) O(n)
= 2T(n/4) 2O(n/2) O(n)
= ...
= O(n) O(n) ... O(n) O(n) O(n)
= k * O(n)
= O(k*n)
= O(nlog2n) //以2为底
一般地,当递归方程为T(n) = aT(n/c) O(n), T(n)的解为:
O(n) (a<c && c>1)
O(nlog2n) (a=c && c>1) //以2为底
O(nlogca) (a>c && c>1) //n的(logca)次方,以c为底
上面介绍的3种递归调用形式,比较常用的是第一种情况,第二种形式也有时出现,而第三种形式(间接递归调用)使用的较少,且算法分析
比较复杂。 下面举个第二种形式的递归调用例子。
<4> 递归方程为:T(n) = T(n/3) T(2n/3) n
为了更好的理解,先画出递归过程相应的递归树:
n --------> n
n/3 2n/3 --------> n
n/9 2n/9 2n/9 4n/9 --------> n
...... ...... ...... ....... ......
--------
总共O(nlogn)
累计递归树各层的非递归项的值,每一层和都等于n,从根到叶的最长路径是:
n --> (2/3)n --> (4/9)n --> (12/27)n --> ... --> 1
设最长路径为k,则应该有:
(2/3)的k次方 * n = 1
得到 k = log(2/3)n // 以(2/3)为底
于是 T(n) <= (K 1) * n = n (log(2/3)n 1)
即 T(n) = O(nlogn)
由此例子表明,对于第二种递归形式调用,借助于递归树,用迭代法进行算法分析是简单易行的。
一个标准的java接口写法
application/x-www-form-urlencoded:application/json:通过上面例子发现,结构简单的时候formdata数据更简单,结构复杂的时候(array)JSON数
java四大名著是哪四本
多了,关键看是哪个出版社出的,一般国内的java书籍主要是由清华大学出版社和电子机械出版社出版的最多,你要是初学者的话建议你看清华大学出版社的java书籍,他们出的书主要针对初学者,内容浅显易懂,初学
java语言的特点
JAVA语言,就是属于混合型语言,这是属于解释型语言和编译型语言之间的一种语言。学习一门高级程序语言,很多人都推荐JAVA。JAVA能让你学习到一门高级程序语言的方方面面,但又不会造成学习曲线过于陡峭
java接口和抽象类的区别
接口是引用类型的,类似于类,和抽象类的相似之处有三点:1、不能实例化;2、包含未实现的方法声明;3、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员);
java如何安装
具体方法如下: 1、查看自己的电脑是32位的还是64位的(x86代表32位的)。java安装要求比较高,楚除了查看系统是windows还是linux等等,如果是windows系统,还要查看是32位的
java安装后没有jdk
那是因为你现在用的是 JRE 7。不信的话 输入这个试试。要么显示为 JDK 6,要么就显示找不到命令。原因是 安装JRE 7时会默认将他们加入环境变量。可能你没有注意在安装JDK时安装软件会弹出JR
implement在java干嘛的
一个父类当然可以有多个子类,你理解错了。java所说的单继承指的是:一个类只能有一个直接的父类,类似classAextendsB,C的语法是不行的但是接口可以实现多个Class A implement
Java面试感觉自己啥也不会
坦然说明自己不会,不过自己可以说下第一次碰到这个问题的思路。首先和问问题的人,确认问题到底是什么,你们两个理解的问题是不是一致的。通过自己已有的知识,聊聊自己对问题的理解,比如为什么会有这个问题,可能