何时需要递归:
public class Recursion_Test {
public static void main(String[] args) {
test(4);
}
//打印问题
public static void test(int n){
System.out.println("函数开头n=" + n);
if(n > 2){
test(n - 1);
}
System.out.println("函数结尾n=" + n);
}
}
【输出】:
函数开头n=4
函数开头n=3
函数开头n=2
函数结尾n=2
函数结尾n=3
函数结尾n=4
public static void main(String[] args) {
System.out.println("1的阶乘:" + factorial(1));
System.out.println("2的阶乘:" + factorial(2));
System.out.println("3的阶乘:" + factorial(3));
}
//阶乘问题
public static int factorial(int n){
if(n == 1){
return 1;
}else{
return factorial(n - 1) * n;
}
}
}
【输出】:
1的阶乘:1
2的阶乘:2
3的阶乘:6
利用数组来模拟小型迷宫,分别用不同的数字代表不同意思,然后利用递归让其自动从初始位置走到终点位置。
//------------------------地图创建-------------------------
int[][] map = new int[10][10];
// 第一行、最后一行:全部置为1
for (int i = 0; i < 10; i++) {
map[0][i] = 1;
map[9][i] = 1;
}
// 最左侧、最右侧列:全部置为1
for (int i = 0; i < 10; i++) {
map[i][0] = 1;
map[i][9] = 1;
}
// 设置挡板
map[3][1] = 1; map[3][2] = 1; map[3][3] = 1;
map[1][5] = 1; map[2][5] = 1; map[3][5] = 1;
map[6][3] = 1; map[6][4] = 1; map[6][5] = 1;
// 输出地图的情况
System.out.println("输出初始地图情况:");
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
输出初始地图情况:
1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 1 0 0 0 1
1 0 0 0 0 1 0 0 0 1
1 1 1 1 0 1 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 1 1 1 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1
//【函数】:使用递归回溯来给小球找路
//1:i,j表示小球的初始位置
//2:数字2表示小球走的路径;
//3:数字3表示该点已经走过,但是走不通
//【策略】:下->右->上->左,如果该点走不通,再回溯
public static boolean setWay(int[][] map, int i, int j){
if(map[8][8] == 2){//通路已经找到
return true;
}else{
if(map[i][j] == 0){//当前这个点还没有走过
//按照策略
map[i][j] = 2;//假定该点可以走通
if(setWay(map, i+1 ,j)){//向下走
return true;
}else if(setWay(map, i ,j+1)){//向右走
return true;
}else if(setWay(map, i-1 ,j)){//向上
return true;
}else if(setWay(map, i ,j-1)){//向左走
return true;
}else{
//说明该点是走不通的,是死路
map[i][j] = 3;
return false;
}
}else{//如果map[1][j] != 0,可能是1 2 3
return false;
}
}
}
【说明】:策略可以根据自己的情况来调整,或者利用其他算法进行优化。
// ------------------使用递归回溯 给小球找路-------------------
setWay(map, 1, 1);
// -----------------------输出新的地图------------------------
System.out.println("小球走过的输出地图情况:");
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
小球走过的输出地图情况:
1 1 1 1 1 1 1 1 1 1
1 2 0 0 0 1 0 0 0 1
1 2 2 2 2 1 0 0 0 1
1 1 1 1 2 1 0 0 0 1
1 0 0 0 2 0 0 0 0 1
1 0 0 0 2 2 2 0 0 1
1 0 0 1 1 1 2 0 0 1
1 0 0 0 0 0 2 0 0 1
1 0 0 0 0 0 2 2 2 1
1 1 1 1 1 1 1 1 1 1
回溯算法的经典案例:在国际象棋8*8的棋盘上摆放8个皇后,使其不能互相攻击(不能放在同一行、同一斜线)。
// 定义一个数组:用来存储每个皇后所放的位置
int[] array = new int[8];
// 定义一个变量:统计解法的个数
static int count = 0;
// 查看我们放置第n个皇后,就去检测该皇后是否和前面已经摆放的皇后冲突
private boolean judge(int n) {
for (int i = 0; i < n; i++) {
// 1.array[i] == array[n]: 判断第n个皇后是否和前面的n-1个皇后在同一列
// 2.Math.abs(n - i) == Math.abs(array[n] - array[i]):判断第n个皇后是否和第i个皇后在同一斜线
if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[n] - array[i])) {
return false;
}
}
return true;
}
// 放置第n个皇后
private void check(int n) {
if (n == 8) {
print();
return;
}
// 依次放入皇后,并判断是否冲突
for (int i = 0; i < 8; i++) {
// 先把当前这个皇后n,放到第i列
array[n] = i;
if (judge(n)) {// 不冲突
// 紧接着放第n+1个皇后,即开始递归
check(n + 1);
}
// 如果冲突i++,就继续执行array[n] = i;即将第n个皇后,放置在本行的 后移的一个位置
}
}
//写一个方法,可以将皇后摆放的位置打印出来
private void print() {
count++;
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
Queue8 queue8 = new Queue8();
queue8.check(0);
System.out.printf("一共有%d解法", count);
}
【输出】:
0 4 7 5 2 6 1 3
0 5 7 2 6 3 1 4
0 6 3 5 7 1 4 2
0 6 4 7 1 3 5 2
1 3 5 7 2 0 6 4
1 4 6 0 2 7 5 3
1 4 6 3 0 7 5 2
1 5 0 6 3 7 2 4
1 5 7 2 0 3 6 4
1 6 2 5 7 4 0 3
1 6 4 7 0 3 5 2
1 7 5 0 2 4 6 3
2 0 6 4 7 1 3 5
2 4 1 7 0 6 3 5
...省略一部分...
5 3 6 0 7 1 4 2
5 7 1 3 0 6 4 2
6 0 2 7 5 3 1 4
6 1 3 0 7 4 2 5
6 1 5 2 0 3 7 4
6 2 0 5 7 4 1 3
6 2 7 1 4 0 5 3
6 3 1 4 7 0 2 5
6 3 1 7 5 0 2 4
6 4 2 0 5 7 1 3
7 1 3 0 6 4 2 5
7 1 4 2 0 6 3 5
7 2 0 5 1 4 6 3
7 3 0 2 5 1 6 4
一共有92解法
public class MiGong {
public static void main(String[] args) {
// ------------------------地图创建-------------------------
int[][] map = new int[10][10];
// 第一行、最后一行:全部置为1
for (int i = 0; i < 10; i++) {
map[0][i] = 1;
map[9][i] = 1;
}
// 最左侧、最右侧列:全部置为1
for (int i = 0; i < 10; i++) {
map[i][0] = 1;
map[i][9] = 1;
}
// 设置挡板
map[3][1] = 1; map[3][2] = 1; map[3][3] = 1;
map[1][5] = 1; map[2][5] = 1; map[3][5] = 1;
map[6][3] = 1; map[6][4] = 1; map[6][5] = 1;
// 输出地图的情况
System.out.println("输出地图情况");
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
// ------------------使用递归回溯 给小球找路-------------------
setWay(map, 1, 1);
// ------------------------输出新的地图-------------------------
System.out.println("小球走过的输出地图情况");
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
// ----------------------------编写函数----------------------------
//【函数】:使用递归回溯来给小球找路
//1:i,j表示小球的初始位置
//2:数字2表示小球走的路径;
//3:数字3表示该点已经走过,但是走不通
//【策略】:下->右->上->左,如果该店走不通,再回溯
public static boolean setWay(int[][] map, int i, int j){
if(map[8][8] == 2){//通路已经找到
return true;
}else{
if(map[i][j] == 0){//当前这个点还没有走过
//按照策略
map[i][j] = 2;//假定该点可以走通
if(setWay(map, i+1 ,j)){//向下走
return true;
}else if(setWay(map, i ,j+1)){//向右走
return true;
}else if(setWay(map, i-1 ,j)){//向上
return true;
}else if(setWay(map, i ,j-1)){//向左走
return true;
}else{
//说明该点是走不通的,是死路
map[i][j] = 3;
return false;
}
}else{//如果map[1][j] != 0,可能是1 2 3
return false;
}
}
}
}
public class Queue8 {
int[] array = new int[8];
static int count = 0;
public static void main(String[] args) {
Queue8 queue8 = new Queue8();
queue8.check(0);
System.out.printf("一共有%d解法", count);
}
// 查看我们放置第n个皇后,就去检测该皇后是否和前面已经摆放的皇后冲突
private boolean judge(int n) {
for (int i = 0; i < n; i++) {
// 1.array[i] == array[n]: 判断第n个皇后是否和前面的n-1个皇后在同一列
// 2.Math.abs(n - i) == Math.abs(array[n] - array[i]):判断第n个皇后是否和第i个皇后在同一斜线
if (array[i] == array[n] || Math.abs(n - i) == Math.abs(array[n] - array[i])) {
return false;
}
}
return true;
}
// 放置第n个皇后
private void check(int n) {
if (n == 8) {
print();
return;
}
// 依次放入皇后,并判断是否冲突
for (int i = 0; i < 8; i++) {
// 先把当前这个皇后n,放到第i列
array[n] = i;
if (judge(n)) {// 不冲突
// 紧接着放第n+1个皇后,即开始递归
check(n + 1);
}
// 如果冲突i++,就继续执行array[n] = i;即将第n个皇后,放置在本行的 后移的一个位置
}
}
//写一个方法,可以将皇后摆放的位置打印出来
private void print() {
count++;
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
}
评论