解决回溯问题,需要考虑三个问题:1、路径:已经做出的选择。2、选择列表:你可以做出的选择。3、结束条件。
模板如下:
List<类型> result = new ArrayList<>();
dfs(选择){
if 满足结束条件
result.add(路径)
for(选择列表做选择){
做选择
dfs(往下遍历)
撤销选择
}
}
leetcode51题N皇后问题
List<List<String>> result = new LinkedList<>();
public List<List<String>> solveNQueens(int n) {
LinkedList<StringBuilder> track = new LinkedList<>();
for(int i = 0; i < n ; i++){
StringBuilder str = new StringBuilder();
for(int j = 0; j < n ; j++){
str.append('.');
}
track.add(str);
}
backtrack(track,0);
return result;
}
public void backtrack(LinkedList<StringBuilder> track, int row){
// 如果每一行都成功放置了皇后,记录结果
if(track.size() == row){
LinkedList<String> track1 = new LinkedList<>();
for(int i = 0; i < track.size() ; i++){
track1.add(track.get(i).toString());
}
result.add(track1);
return ;
}
int n = track.get(row).length();
for(int col = 0; col < n; col++){
//排除不合法选择
if(!isValid(track,row,col))
continue;
//做选择
track.get(row).setCharAt(col,'Q');
backtrack(track,row+1);
//撤销选择
track.get(row).setCharAt(col,'.');
}
}
public boolean isValid(LinkedList<StringBuilder> track,int row,int col){
int n = track.size();
//检查列是否有冲突
for(int i = 0; i < n; i++){
if(track.get(i).charAt(col) == 'Q')
return false;
}
//检查左上方是否有冲突
for(int i = row - 1,j = col - 1; i >= 0 && j >= 0; i--,j--){
if(track.get(i).charAt(j) == 'Q')
return false;
}
//检查右上方是否有冲突
for(int i = row - 1,j = col + 1; i >= 0 && j < n ; i--,j++){
if(track.get(i).charAt(j) == 'Q')
return false;
}
return true;
}