递归
递归
递归 -自己调用自己的函数
使用场景
- 8 皇后,汉诺塔,阶乘,迷宫
- 快排,归并,二分,分治
- 使用栈解决的问题->递归代码比较简洁
使用递归需要遵守的问题
- 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
- 方法的局部变量是独立的,不会相互影响
- 每个递归定义至少必须有一个条件,满足时递归不再进行,而是返回值退出
- 遵守谁调用,就将结果返回谁,方法执行完毕或者返回时,该方法也就执行完毕
- 如果方法中,用到引用类型的变量,则会共享
迷宫回溯
1.成功条件 是终点可以走的通 即状态 2 2.中间有个分支如果出现走不通,即开始回溯,分支即判断 false,所有分支都判断为 false 则该点 即为 3 3.递归至终点,并且可以走通,回溯完成当前路径,则是行的通的路径
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package com.learn.recursion;
//迷宫回溯
public class Maze {
public static void main(String[] args) {
//数组标记 0 可走节点 ,1 障碍物, 2 走的通的节点 ,3 走不通的节点
var map = CreateMaze(6,7);
int sizeX=map.length;
int sizeY=map[0].length;
//设置障碍
map[2][1]=1;
map[2][2]=1;
//开始走出迷宫
GoMaze(map,1,1);
for(int i=0;i<sizeX;i++) {
for (int j = 0; j < sizeY; j++) {
System.out.print(map[i][j]+" ");
}
System.out.println();
}
}
//创建迷宫
public static int[][] CreateMaze(int sizeX,int sizeY)
{
int[][] map= new int[sizeX][sizeY];
for(int i=0;i<sizeX;i++)
for(int j=0;j<sizeY;j++)
{
if(i==0||i==sizeX-1||j==0||j==sizeY-1)
{
map[i][j]=1;
}else{
map[i][j]=0;
}
}
return map;
}
//走出迷宫
//策略 下->右->上->左
/*
*x,y开始节点 map迷宫
*/
public static boolean GoMaze(int[][] map,int sx,int sy)
{
for(int i=0;i<6;i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j]+" ");
}
System.out.println();
}
System.out.println("-----------------------------------------");
//终止循环
if(map[4][5]==2)
{
return true;
}else
{
if(map[sx][sy]==0)
{
map[sx][sy]=2;
if(GoMaze(map,sx+1,sy))
{
return true;
}else if(GoMaze(map,sx,sy+1))
{
return true;
}else if(GoMaze(map,sx-1,sy))
{
return true;
}else if(GoMaze(map,sx,sy-1))
{
return true;
}
map[sx][sy]=3;
return false;
}else
{
return false;
}
}
}
}
8 皇后问题算法(回溯算法)
思路
- 第一个皇后放在第一行第一列
- 第二个皇后放在第二行第一列,判断是否 ok,如果不 ok 则继续往第二列第三列放
- 当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后放在第一个列时的正确解将全部得到
- 后续依次将第一个皇后放在第二列,第三列。。。
- 这里用一维数组表示棋盘 e.g arr[] ={1,1},下表表示 index+1 行,对应的值表示 value+1 列
实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package com.learn.recursion;
//8皇后问题
public class Queen {
public static void main(String[] args)
{
Queen8 queen8=new Queen8();
queen8.StarPut();
}
}
class Queen8{
//皇后数量
int queen_num=8;
int[] arr=new int[queen_num];
public void StarPut()
{
PutQueen(0);
}
//放入棋子
public void PutQueen(int n)
{
//n==8 即第九行的棋子,前面8个符合8皇后规则
if(n==queen_num)
{
//递归完成,打印当前的棋子
Log();
return;
}
for(int i=0;i<queen_num;i++)
{
//把棋子放在第n+1行的第i+1列
arr[n]=i;
//如果符合 8皇后规则
if(Check(n))
{
//则继续放下一行
PutQueen(n+1);
}
}
}
//判断当前放入的列是否符合规则
public boolean Check(int n)
{
for(int i=0;i<n;i++)
{
//arr[i]==arr[n] 列值相等
//Math.abs(arr[i]-arr[n]在对角线上
if(arr[i]==arr[n]||Math.abs(n-i)==Math.abs(arr[i]-arr[n]))
{
return false;
}
}
return true;
}
//输出值
public void Log()
{
for(int i=0;i<queen_num;i++)
{
System.out.print(arr[i]+" ");
}
//h换行
System.out.println();
}
}
本文由作者按照 CC BY 4.0 进行授权