写在前面
递归
- 方法自己调用自己,每次调用时传入不同的变量
- 调用机制,依次入栈执行,最终可以打破自己调用自己的循环,一个个出栈(后进先出)
注意事项
- 执行一个方法时,就创建一个受保护的独立空间(栈空间);
- 方法的局部变量是独立的,不会相互影响;
- 如果方法中使用的是引用类型的变量,就会共享该引用类型变量(如数组);
- 递归必须向推出递归的条件逼近,否则就是无限递归,出现异常
StackOverFlowError
;
- 当一个方法执行完毕,遇到return放回,遵守谁调用,将结果返回给谁,方法执行完毕,这层方法也出栈
迷宫回溯问题
- 走出迷宫的最短路径
- 通过假设的方式,不断向下一个点尝试,直到有返回值后,依次倒序回溯,影响最初的点
- 例如
A
点有四个方位,每个方位尝试过后,再将A
自身的结果返回给A
的上一个,而A
的尝试中,也包括A
的下一个的尝试,不断包含
- 每一个点都在自己这个位置进行四个方向的尝试,并影响上一个点
public static boolean getWay(int[][] mazeArr, int i, int j) {
if(mazeArr[6][5] == 2) {
return true;
} else {
if (mazeArr[i][j] == 0) {
mazeArr[i][j] = 2;
if (getWay(mazeArr, i + 1, j)) {
return true;
} else if (getWay(mazeArr, i, j + 1)) {
return true;
} else if (getWay(mazeArr, i - 1, j)) {
return true;
} else if (getWay(mazeArr, i, j - 1)) {
return true;
} else {
mazeArr[i][j] = 3;
return false;
}
} else {
return false;
}
}
}
最短路径
- 通过调整策略,实际上有
4*4=16
种策略,下面的笨方法只写了四组试试看
- 调用,
countAndShowAndRecover
方法里面实现了记录2的个数、地图输出和还原
;将每个策略2的个数,存到ArrayList
,然后排个序输出最小的,也可以存在map更好
//通过4*8的数组决定四种策略
// 10 01 -10 0-1 下 右 上 左
int[] up = new int[]{-1, 0}
int[] down = new int[]{1, 0}
int[] right = new int[]{0, 1}
int[] left = new int[]{0, -1}
//上下右左
List<int[]> strategy1 = Arrays.asList(up, down, right, left)
//下上左右
List<int[]> strategy2 = Arrays.asList(down, up, left, right)
//左上右下
List<int[]> strategy3 = Arrays.asList(left, up, right, down)
//右下上左
List<int[]> strategy4 = Arrays.asList(right, down, up, left)
HashMap<String, List<int[]>> strategies = new HashMap<>()
strategies.put("strategy1", strategy1)
strategies.put("strategy2", strategy2)
strategies.put("strategy3", strategy3)
strategies.put("strategy4", strategy4)
Set<String> set = strategies.keySet()
ArrayList<Integer> counts = new ArrayList<>()
for (String s : set) {
List<int[]> strategy = strategies.get(s)
System.out.println("--------" + s + "---------")
getWay(mazeArr, 1,1, strategy)
counts.add(countAndShowAndRecover(mazeArr))
}
counts.sort((o1, o2) -> o1 - o2)
System.out.println("4个策略的最短路径: " + counts.get(0))
public static boolean getWay(int[][] mazeArr, int i, int j, List<int[]> strategy) {
....
if (mazeArr[i][j] == 0) {
mazeArr[i][j] = 2;
if (getWay(mazeArr, i + strategy.get(0)[0], j + strategy.get(0)[1], strategy)) {
return true;
} else if (getWay(mazeArr, i+ strategy.get(1)[0], j + strategy.get(1)[1], strategy)) {
return true;
} else if (getWay(mazeArr, i + strategy.get(2)[0], j+ strategy.get(2)[1], strategy)) {
return true;
} else if (getWay(mazeArr, i+ strategy.get(3)[0], j + strategy.get(3)[1], strategy)) {
return true;
}
....
}
八皇后问题
- 8*8的方格上,任意两个皇后不能在
同一列,同一行,同一斜线

- 每次递归都改变当前一个皇后的位置,再来决定下面的皇后位置;
- 比如说
1 2 3 4
要排列组合,先固定1
再固定2
,修改3 4
的位置;固定1
再固定3
修改2 4
的位置···,只不过八皇后问题有额外的要求
- 调用,从第0个皇后开始
eq.check(0)
private void check(int n) {
if (n == max) {
print();
return;
}
for (int i = 0; i < max; i++) {
arr[n] = i;
if (judge(n)) {
check(n+1);
}
}
return;
}
private boolean judge(int n) {
for (int i = 0; i < n; i++) {
if (arr[i] == arr[n]
|| Math.abs(n-i) == Math.abs(arr[n] - arr[i])) {
return false;
}
}
return true;
}
- 输出结果
private void print() {
count ++;
for (int i : arr) {
System.out.print(i + " ");
}
System.out.println();
}