題目描述
回溯算法經典思路
- 尋找路徑。
- 根據路徑,每個節點做出選擇,繼續向下尋找。
- 撤銷選擇。
算法框架
result = []
def backtrack(路徑, 選擇列表):
if 滿足結束條件:
result.add(路徑)
return
for 選擇 in 選擇列表:
做選擇
backtrack(路徑, 選擇列表)
撤銷選擇
回溯算法解決N皇后問題
/**
* @description:
* @author: lilang
* @version:
* @modified By:[email protected]
*/
public class ListSolution {
//定義返回節點位置
List<List<String>> solutions = new ArrayList<List<String>>();
public List<List<String>> solveNQueens(int n) {
// 初始化皇后棋盤 初始值設置爲‘.’
char[][] board = new char[n][n];
for (int i = 0; i < board.length; i++) {
Arrays.fill(board[i], '.');
}
//對棋盤進行逐行遍歷,這也是題目中所說的路徑方向
backtrack(board, 0);
return solutions;
}
/**
* 棋盤迴溯
* @param board 動態賦值過的棋盤
* @param row 遍歷的當前行數
*/
void backtrack(char[][] board, int row) {
/**
* 說明已經可以終止循環,已經到達最後一行了
*
*/
if (row == board.length) {
solutions.add(array2List(board));
return;
}
/**
* 對每一行的元素進行檢測
*/
for (int col = 0; col < board[row].length; col++) {
/**
* 判斷是否滿足皇后要求
*/
if (findIsValid(board, row, col)) {
//如果滿足,選擇當前位置變爲皇后
board[row][col] = 'Q';
//向下繼續執行
backtrack(board, row + 1);
//撤銷當前選擇
board[row][col] = '.';
}
}
}
private boolean findIsValid(char[][] board, int row, int col) {
// 檢查列是否有皇后互相沖突
for (int i = 0; i < row; i++) {
if (board[i][col] == 'Q')
return false;
}
// 檢查右上方是否有皇后互相沖突
for (int i = row - 1, j = col + 1; i >= 0 && j < board.length; ) {
if (board[i][j] == 'Q') {
return false;
}
i--;
j++;
}
// 檢查左上方是否有皇后互相沖突
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; ) {
if (board[i][j] == 'Q') {
return false;
}
i--;
j--;
}
return true;
}
private List<String> array2List(char[][] board) {
List<String> res = new LinkedList<>();
for (char[] i : board) {
StringBuffer sb = new StringBuffer();
for (char j : i) {
sb.append(j);
}
res.add(sb.toString());
}
return res;
}
}