目录
参考资料:
参考文章 https://blog.csdn.net/m0_57668040/article/details/119295564
1.迭代简述:
我们常用的循环其实就是迭代,比如:for,while,do ... while...循环等,都属于迭代。
2.递归/递推
(1).递归
1).简述
- 递归是通过方法的自调用,将输入条件推至边界条件,然后再由边界条件,反方向进行累积或累加,最后得到结果。
- 递归往往是只知道边界条件的结果,进行逆向推导
2).推理过程
- 函数调用过程有一个如下现象,比如:A→B→C
- 调用过程为:
- 输出为:
- 以求5的阶乘5!为例,数学推导式如下:
- 用最原始的方法实现如下:
- 它的调用图如下:
- 但是这么做很繁琐,而且当5变为N时,就会产生很多重复的代码,我们根据特点总结为:
- 然后它的入参和回参可以这么观察
- f(n)及f(0)括号中的类型,即为函数的入参,此处 int
- n * f(n-1),确定了该函数有返回值,因为只有f(x)有返回值,n才能去乘它
- 根据f(0) = 1 的 “= 1”进一步确定返回值为int
- n = 0:f(0) = 1,为终止条件,写入函数体中
- n >0 :f(n) = n * f(n-1),为递归条件,写入函数体中
- 所以结果为:
@Test
public void A(){
System.out.println("5 的阶乘为:" + function(5));
}
public int function(int num){
if(num == 0){
return 1;
}else{
return num * function(num - 1);
}
}
3).总结
- 递归函数的书写过程可以可以概括为:
- 我们以斐波那契数列进行讲解:
- 有一个数列:第一项为1,第二项为1,之后的每一项都是前两项之后,求前100项之和
- 那么这个数列可以写为:
1,1,2,3,5,8,13,... ...
- 首先要把具象改为有结束条件的抽象等式
- 然后看f(n),f(2),f(1)即可确定入参为 int类型
- 根据他们的组合方式:f(n-1) + f(n-2),知道他们有返回值,因为只有f(x)有返回值,才能用他们相加
- 通过f(2) = 1的1,确定回参为int类型
- 确定了入参和回参,起个函数名,然后把终止条件以及递归条件填入即可
@Test
public void A(){
System.out.println("前100个斐波那契数列和为:" + function(100));
}
public int function(int num){
if(num == 1||num == 2){
return 1;
}else if(num > 2){
return function(num-1)+function(num-2);
}else{
System.out.println("error");
return 0;
}
}
(2).递推
1).简述
- 递推是从初始条件就可以进行操作,通过对自身的调用,一直到末尾条件
- 递推常用于遍历,统计
2).推理过程
- 以将字符串的每个字符放在list中为例:
- 那么代码将写为:
- 但是这么写太麻烦了, 我们把上面的公式进行抽象化
- 观察公式中的公式,进行参数的确定:
- 根据迭代关系式:
f(str(0,n)) = list.add(str(0,1)) && f(str(1,n))
中的&&与关系,因为是并列的操作,所以不需要返回值,即为void
- 同样,迭代关系式,list是统计工具,所以需要作为参数进行传递
- 根据f(str(0,n)) ,确定入参还有string 类型
- 确定了,入参和回参后,再将终止条件和迭代条件加入即可:
迭代条件:
str长度 > 1:
f(str(0,n)) = list.add(str(0,1)) && f(str(1,n))
终止条件:
str长度 = 1:
f(str(0,1)) = list.add(str(0,1))
- 最后得到结果
@Test
public void A(){
List<String> list = new ArrayList<>();
String str = "abcdefg";
function(str,list);
list.forEach(x->{System.out.println(x);});
}
public void function(String str,List<String> list){
if(str.length() == 1){
list.add(str);
}
else if(str.length() > 1){
list.add(str.substring(0,1));
function(str.substring(1),list);
}else{
System.out.println("error");
}
}
3).总结
- 递推函数书写步骤如下:
- 以统计一个数字,各个位上数字的三次方为例(当然用循环迭代也可以,这里主要是用来讲解递推)
- 统计数字:56753951各个位上数字三次方组合成的list
- 递推关系以及抽象结果如下:
- 根据迭代关系式:
n > 10:
f(n) = list.add((n%10)^3) && f(n / 10)
- 中的与关系(&&),即并列操作,所以不需要返回值,void
- 根据结束关系式:
n < 10:
f(n) = list.add(n^3)
- 中的n<10,确定入参为int类型
- 根据迭代关系式,list作为存储器,需要一级一级传下去,所以list也需要作为参数进行传递
- 然后将结束条件和迭代条件写入,最后得到
@Test
public void A(){
List<Integer> list = new ArrayList<>();
Integer num = 56753951;
function(num,list);
list.forEach(x->{System.out.println(x);});
}
public void function(Integer num,List<Integer> list){
if(num < 10){
list.add(num);
}
else if(num > 10){
list.add(num%10);
function(num/10,list);
}else{
System.out.println("error");
}
}