关于递归
关于递归的理解:
/**
* 关于递归的实际理解
* @author Viaxiz
*/
public class Dugui2 {
public static void f(int n) {
if(n>0) {
f(n-1);
System.out.print(n+" ");
f(n-1);
}
}
//递归就是把自己当作语句调用,所以为了完成语句的执行,其后面必然会出来的,
//想想栈的原理,先进后出,最开始调用的方法即最后一次执行的方法
//因为执行递归语句后还要执行递归语句剩下的
public static void main(String[] args) {
f(3);
}
}
先猜猜输出是什么吧
1 2 1 3 1 2 1
推荐哔哩哔哩上的陈越姥姥讲浙大数据结构
陈越姥姥讲递归:
- 重点:
- 出口在哪
- 递推性(相似性)
a. 相似而规模逐渐变小,以参数体现
b. 若没有明显的相似性,就需要主动构造
a) 关于递归,记得从最开始先一步一步地推,找出其中的规律(关系)
例如:
汉诺塔
黑白球
以及常见的:
输出逆序字符串
整数划分
递归的常见形式
- 尾递归
- 非尾递归
关于递归总给我以下感觉:
- 找规律
- 判定条件;
a. return
b.注意两个或多个变量值传入,其中的有些值是要相应变化的
递归的简单应用:
用来生成一个数组的全排列,这个怎么写呢?数重for循环是不是太难写了点了,所以想想用递归试试吧,当然在C++中有std :: next_permutation方法可用,不过这里我们用Java来写一个生成0-9之间所有数字的全排列数组吧
/**
* 生成全排列的数组,并输出生成的全排列数组
*
* @author ASUS
*
*/
public class Permutaition {
public static int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
public static int ans = 0;
public static void main(String[] args) {
range(a, 0, a.length - 1);
if (10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 == ans)//我只是确认一下全排列的数组有多少种
System.out.println(true);
}
public static void range(int[] arr, int start, int end) {
if (start == end) {
// write(arr)输出生成的全排列数组元素
System.out.println(
"" + arr[0] + arr[1] + arr[2] + arr[3] + arr[4] + arr[5] + arr[6] + arr[7] + arr[8] + arr[9]);
ans++;
return; // 无返回值,只是起到退出的作用
}
// 核心代码
for (int i = start; i <= end; i++) {
swap(arr, i, start);
range(arr, start + 1, end);
swap(arr, i, start); // 没看懂啊=…=
}
}
// 将元素交换
public static void swap(int[] arr, int x, int y) {
int tmp = arr[x];
arr[x] = arr[y];
arr[y] = tmp;
}
}
深搜(DFS)
深搜最重要的就是正确表示状态
如,部分和的问题:
部分和的这个问题……我没写出来…,看下老师给的参考代码:
李白打酒这题…也太…那啥了~
代码示例:
关于六角形的问题,哈哈哈哈哈哈哈哈哈哈哈~,全排列大法好啊!!!一次过。
但是我们也还是看看深搜的解法吧
核心代码:
关于深搜和广搜:
深搜是用递归来实现的,其好像栈一样
广搜主要使用队列来实现的,先进先出的原则
附:
简单理解,广搜和暴力有啥区别啊?多了队列和剪枝??
暴力枚举,搜索状态。
深搜在判断不是最终结果后,其执行的其实是接下来的状态语句
如,接下来的状态用循环表示;
常见的深搜模型如下
以及不用循环表示的情况:
关于递推:
参考链接
当n=1:
当n=2:有7种走法,也就是绿色线条的数量
当n=3:
同样的道理,至于两个点的,我们只需要将减去三个点的即得到两个点的情况了。
所以得到递推的关系式为:
关于Java中的容器
顺势感叹一波这段时间过得太快了啊,从开年到现在,从准备完蓝桥杯到现在,时间真的好快好快啊!少年回头看,笑我还不快跟上!!!