51. N皇后
关键点1:结束条件,当 row==n 时,代表遍历完所有行了,可以直接返回根节点的结果了
关键点2:单层循环条件
2-1:每行的行是固定的,相当于变化的是col,去确定每行具体放哪个位置:;
2-2:需要有一个判断放的位置是否合法的函数,调用函数,如果合法,则chessBoard[row][col] = 'Q';然后递归到下一层,row+1,然后chessBoard[row][col] = '.'
关键点3:判断放的位置是否合法的函数
3-1:每行只加一个,所以只有判断列是否符合条件;
3-2:判断左45度是否符合条件,条件用与:i >=0 && j>= 0;
3-3:判断右135度是否符合条件,条件用与:i >=0 && j < n;
关键点4:将char[][] 转化为List<String>,以便加入后面的res
class Solution {
List<List<String>> res = new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
char[][] chessBoard = new char[n][n];
// 初始化chessBoard数组
for(char[] i:chessBoard){
Arrays.fill(i,'.');
}
backTracking(chessBoard,n,0);
return res;
}
public void backTracking(char[][] chessBoard,int n,int row){
// 结束条件
if(row == n){
res.add(Array2List(chessBoard));
return;
}
// 单层循环条件
for(int col = 0; col < n; col++){
if(isQ(row,col,chessBoard,n)){
chessBoard[row][col] = 'Q';
backTracking(chessBoard,n,row+1);
chessBoard[row][col] = '.';
}
}
}
// 将char[][] 转化为List<String>
public List Array2List(char[][] chessboard) {
List<String> list = new ArrayList<>();
for (char[] c : chessboard) {
list.add(String.copyValueOf(c));
}
return list;
}
public boolean isQ(int row,int col,char[][] chessBoard,int n){
// 每行只加一个,所以只有判断列是否符合条件
for(int i =0; i < row;i++ ){
if(chessBoard[i][col] =='Q'){
return false;
}
}
// 判断左45度是否符合条件,条件用与:i >=0 && j>= 0;
for(int i =row-1,j = col-1; i >=0 && j>= 0;i--,j-- ){
if(chessBoard[i][j] =='Q'){
return false;
}
}
// 判断右135度是否符合条件,条件用与:i >=0 && j < n;
for(int i = row-1,j = col+1; i >= 0 && j < n;i--,j++){
if(chessBoard[i][j] =='Q'){
return false;
}
}
return true;
}
}
37. 解数独
关键点1:
1-1:两层for 遍历行,遍历列,确定每个格子的元素;
1-2:用if(board[i][j] == '.')判断这个位置放k是否合适;
1-3:用for循环将k='1'遍历到k='9',判断是否满足条件,不满足则循环结束返回false;
1-4:循环内部需要判断:这个board[i][j]位置放k是否合适,写一个判断k是否合适的函数;如果合适,就把k值给这个位置,递归,进入下一个位置的判断,再将这个位置的值改为'.'
1-5:两层for遍历完都没有返回false,说明找到了合适棋盘位置了,在循环结束返回TRUE;
关键点2:判断k是否合适的函数
2-1:同行是否重复,行不变,列++;
2-2:同列是否重复:列不变,行++;
2-3:九宫格是否重复
1)确定此时行列位置初始行和初始列的位置 int startRow = (row / 3) * 3; int startCol = (col / 3) * 3;
2)两层for循环i,j遍历9宫格的元素,如果有元素和k的值相同,则返回false,否则循环结束,返回true;
int i = startRow; i < startRow + 3; i++;int j = startCol; j < startCol+ 3; j++
class Solution {
public void solveSudoku(char[][] board) {
backTracking(board);
}
public boolean backTracking(char[][] board){
for(int i = 0;i < board.length;i++){// 遍历行
for(int j = 0 ;j < board.length;j++){// 遍历列
if (board[i][j] != '.'){ // 跳过原始数字
continue;
}
if(board[i][j] == '.'){ // 这个位置放k是否合适
for(char k = '1';k <= '9';k++){
if(isT(board,i,j,k)){
board[i][j] = k;
//如果找到合适一组立刻返回
if (backTracking(board)){
return true;
}
board[i][j] = '.';
}
}
// 如果9个数都尝试都不行,证明有空没办法填上,肯定返回FALSE
return false;
}
}
}
// 遍历完没有返回false,说明找到了合适棋盘位置了
return true;
}
public boolean isT(char[][] board,int row,int col,char k){
//判断棋盘是否合法有如下三个维度:
// 同行是否重复
for (int j = 0; j < 9; j++){
if (board[row][j] == k){
return false;
}
}
// 同列是否重复
for (int i = 0; i < 9; i++){
if (board[i][col] == k){
return false;
}
}
// 9宫格里是否重复
int startRow = (row / 3) * 3;
int startCol = (col / 3) * 3;
for (int i = startRow; i < startRow + 3; i++){
for (int j = startCol; j < startCol + 3; j++){
if (board[i][j] == k){
return false;
}
}
}
return true;
}
}