【LeetCode每日一题】[困难]52. N皇后 II

【LeetCode每日一题】[困难]52. N皇后 II

52. N皇后 II

题目来源
算法思想:回溯

题目:
在这里插入图片描述
题目分析
在这里插入图片描述

java代码

class Solution {
    
    
	boolean[] columns;//用来标记列是否有Q
	boolean[] diagonals1;//用来标记正对角线是否有Q
	boolean[] diagonals2;;//用来标记反对角线是否有Q
	int count = 0;//用于计数,有多少种方法

	public int totalNQueens(int n) {
    
    
	//初始化
		columns = new boolean[n];//行列长度范围: 0到n-1
		//正对角线范围i-j: -(n-1)到n-1,
		//利用i-j+n映射到0-2n范围进行存放, 初始化用2n长度来存放
		diagonals1 = new boolean[n * 2];
		//反对角线范围i+j: 0到2*(n-1)
		//初始化用2n长度来存放
		diagonals2 = new boolean[n * 2];
		backtrack(n, 0);//回溯
		return count;//返回计数
    }
	private void backtrack(int n, int i) {
    
    
		//如果递归到了n层,说明前面n-1层都已经填写好了,即找到了答案,计数++;
		if (i == n) {
    
    
			count++;
			return;
		}
		for (int j = 0; j < n; j++) {
    
    //从0开始在i行尝试j列
			if (columns[j] == true) {
    
    //列重复,尝试下一个可能列j
				continue;
			}
			int diagonal1 = i - j + n;//计算正对角线
			int diagonal2 = i + j;//计算反对角线
			if (diagonals1[diagonal1] == true) {
    
    //正对角线重复,尝试下一个可能列j
				continue;
			}
			if (diagonals2[diagonal2] == true) {
    
    //反对角线重复,尝试下一个可能列j
				continue;
			}
			//以上条件均没有重复,即可以在j列填入Q
			columns[j] = true;//将列设置占有
			diagonals1[diagonal1] = true;//将正对角线设置占有
			diagonals2[diagonal2] = true;//将反对角线设置占有
			backtrack(n, i+1);//向下递归,尝试下一行的Q的填法
			//递归结束,将j列取消填写,尝试下一个j
			columns[j] = false;//将列设置未占有
			diagonals1[diagonal1] = false;//将正对角线设置未占有
			diagonals2[diagonal2] = false;//将反对角线设置未占有
		}
	}
}

51. N 皇后

题目来源
算法思想:回溯

题目:相比于52题,这个要输出棋盘;
在这里插入图片描述
思路:同上,只是要将棋盘保存下来

java代码

class Solution {
    
    
	boolean[] columns;//用来标记列是否有Q
	boolean[] diagonals1;//用来标记正对角线是否有Q
	boolean[] diagonals2;;//用来标记反对角线是否有Q
	char[][] path;//用来存放棋盘
	List<List<String>> res = new ArrayList<List<String>>();//返回答案
	
	public List<List<String>> solveNQueens(int n) {
    
    
	//初始化
		columns = new boolean[n];//行列长度范围: 0到n-1
		//正对角线范围i-j: -(n-1)到n-1,
		//利用i-j+n映射到0-2n范围进行存放, 初始化用2n长度来存放
		diagonals1 = new boolean[n * 2];
		//反对角线范围i+j: 0到2*(n-1)
		//初始化用2n长度来存放
		diagonals2 = new boolean[n * 2];
		//初始化棋盘
        path = new char[n][n];
		for (int i = 0; i < n; i++) {
    
    
			for (int j = 0; j < n; j++) {
    
    
				path[i][j] = '.';
			}
		}
		backtrack(n, 0);
		return res;
    }
	private void backtrack(int n, int i) {
    
    
		//如果递归到了n层,说明前面n-1层都已经填写好了,即找到了答案,计数++;
		if (i == n) {
    
    
			List<String> tmp = new ArrayList<>();//String列表,放入棋盘
			for (int j = 0; j < n; j++) {
    
    
				tmp.add(new String(path[j]));//将path数组每行变成一个字符串
			}
            res.add(tmp);//将整个棋盘tmp放入res中
			return;
		}
		for (int j = 0; j < n; j++) {
    
    //从0开始在i行尝试j列
			if (columns[j] == true) {
    
    //列重复,尝试下一个可能列j
				continue;
			}
			int diagonal1 = i - j + n;//计算正对角线
			int diagonal2 = i + j;//计算反对角线
			if (diagonals1[diagonal1] == true) {
    
    //正对角线重复,尝试下一个可能列j
				continue;
			}
			if (diagonals2[diagonal2] == true) {
    
    //反对角线重复,尝试下一个可能列j
				continue;
			}
			//以上条件均没有重复,即可以在j列填入Q
			path[i][j] = 'Q';
			columns[j] = true;//将列设置占有
			diagonals1[diagonal1] = true;//将正对角线设置占有
			diagonals2[diagonal2] = true;//将反对角线设置占有
			backtrack(n, i+1);//向下递归,尝试下一行的Q的填法
			//递归结束,将j列取消填写,尝试下一个j
			path[i][j] = '.';
			columns[j] = false;//将列设置未占有
			diagonals1[diagonal1] = false;//将正对角线设置未占有
			diagonals2[diagonal2] = false;//将反对角线设置未占有
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_39457586/article/details/109131504