经典回溯法
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
给定 word = "ABCCED", 返回 true
给定 word = "SEE", 返回 true
给定 word = "ABCB", 返回 false
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-search
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public boolean exist(char[][] board, String word) {
int m = board.length;
int n = board[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
//对每一个字母搜索
if(search(board, i, j, 0, word)) return true;
}
}
return false;
}
//相当与dfs
private boolean search(char[][] board, int i, int j, int k, String word) {
//终止条件
if( k >= word.length()) return true;
//剪枝 在这些情况的需要返回
if( i < 0 || j < 0 || i >= board.length || j >= board[0].length || board[i][j] != word.charAt(k))
return false;
//加52之后判断一定被剪纸
board[i][j] += 52;
//继续搜索
boolean res = search(board,i+1, j, k+1, word) || search(board,i-1, j, k+1, word)
|| search(board, i, j+1, k+1, word) || search(board, i, j-1, k+1, word);
board[i][j] -= 52;
return res;
}
}
回溯法再来看一个八皇后问题
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。
第一种 迭代的方法 空间效率低
class Solution {
public List<List<String>> solveNQueens(int n) {
char[][] chess = new char[n][n];
//初始化数组
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
chess[i][j] = '.';
}
}
List<List<String>> res = new ArrayList<>();
slove(res, chess, 0);
return res;
}
private void slove(List<List<String>> res, char[][] chess, int row) {
//终止条件
if(row == chess.length) {
res.add(construct(chess));
return;
}
//遍历每一行
for (int col = 0; col < chess.length; col++) {
//判断当前位置可否放皇后
if(vaild(chess, row, col)){
//数组复制
char[][] temp = copy(chess);
//当前位置放置皇后
temp[row][col] = 'Q';
//递归下一行
slove(res, temp, row+1);
}
}
}
private List<String> construct(char[][] chess) {
List<String> path = new ArrayList<>();
for (int i = 0; i < chess.length; i++) {
path.add(new String(chess[i]));
}
return path;
}
//row第几行 col第几列
private boolean vaild(char[][] chess, int row, int col) {
//判断当前列能不能放皇后
for (int i = 0; i < row; i++) {
if(chess[i][col] == 'Q'){
return false;
}
}
//判断右上角有没有皇后
for(int i = row - 1, j = col + 1; i >= 0 && j < chess.length ; i --, j ++){
if(chess[i][j] == 'Q'){
return false;
}
}
//判断左上角
for(int i = row - 1, j = col - 1; i >= 0 && j >= 0; i --, j --){
if(chess[i][j] == 'Q'){
return false;
}
}
return true;
}
private char[][] copy(char[][] chess) {
char[][] temp = new char[chess.length][chess.length];
for (int i = 0; i < chess.length; i++) {
for (int j = 0; j < chess.length; j++) {
temp[i][j] = chess[i][j];
}
}
return temp;
}
}
这里使用回溯的方法,将放上去的皇后更改回来
class Solution {
public List<List<String>> solveNQueens(int n) {
char[][] chess = new char[n][n];
//初始化数组
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
chess[i][j] = '.';
}
}
List<List<String>> res = new ArrayList<>();
slove(res, chess, 0);
return res;
}
private void slove(List<List<String>> res, char[][] chess, int row) {
//终止条件
if(row == chess.length) {
res.add(construct(chess));
return;
}
//遍历每一行
for (int col = 0; col < chess.length; col++) {
//判断当前位置可否放皇后
if(vaild(chess, row, col)){
//这个地方回溯法不走数组的复制了
//这里进行搜索下一行 如果回来了 那么把这个地方复原
//char[][] temp = copy(chess);
//当前位置放置皇后
chess[row][col] = 'Q';
//递归下一行
slove(res, chess, row+1);
chess[row][col] = '.';
}
}
}
private List<String> construct(char[][] chess) {
List<String> path = new ArrayList<>();
for (int i = 0; i < chess.length; i++) {
path.add(new String(chess[i]));
}
return path;
}
//row第几行 col第几列
private boolean vaild(char[][] chess, int row, int col) {
//判断当前列能不能放皇后
for (int i = 0; i < row; i++) {
if(chess[i][col] == 'Q'){
return false;
}
}
//判断右上角有没有皇后
for(int i = row - 1, j = col + 1; i >= 0 && j < chess.length ; i --, j ++){
if(chess[i][j] == 'Q'){
return false;
}
}
//判断左上角
for(int i = row - 1, j = col - 1; i >= 0 && j >= 0; i --, j --){
if(chess[i][j] == 'Q'){
return false;
}
}
return true;
}
private char[][] copy(char[][] chess) {
char[][] temp = new char[chess.length][chess.length];
for (int i = 0; i < chess.length; i++) {
for (int j = 0; j < chess.length; j++) {
temp[i][j] = chess[i][j];
}
}
return temp;
}
}