51. N 皇后
题解:
class Solution {
private int n;
private boolean[] col;
private boolean[] master;
private boolean[] slave;
private List<List<String>> res;
public List<List<String>> solveNQueens(int n) {
this.n = n;
col = new boolean[n];
master = new boolean[2 * n - 1];
slave = new boolean[2 * n - 1];
res = new ArrayList<>();
Deque<Integer> stack = new ArrayDeque<>();
dfs(0, stack);
return res;
}
private void dfs(int row, Deque<Integer> stack) {
if (row == n) {
List<String> board = covert2Board(stack, n);
res.add(board);
return;
}
for (int i = 0; i < n; i ++) {
if (!col[i] && !master[row + i] && !slave[row - i + n - 1]) {
stack.addLast(i);
col[i] = true;
master[row + i] = true;
slave[row - i + n - 1] = true;
dfs(row + 1, stack);
col[i] = false;
master[row + i] = false;
slave[row - i + n - 1] = false;
stack.removeLast();
}
}
}
// 保存一个结果的stack,皇后数量:n
private List<String> covert2Board(Deque<Integer> stack, int n) {
List<String> board = new ArrayList<>();
for (Integer num : stack) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i ++) {
sb.append(".");
}
sb.replace(num, num + 1, "Q");
board.add(sb.toString());
}
return board;
}
}
46. 全排列
题解:
class Solution {
public List<List<Integer>> permute(int[] nums) {
Deque<Integer> path = new ArrayDeque<>();
List<List<Integer>> res = new ArrayList<>();
boolean[] visited = new boolean[nums.length];
dfs(nums, -1, visited, path, res);
return res;
}
private void dfs(int[] nums, int index, boolean[] visited, Deque<Integer> path, List<List<Integer>> res) {
final int n = nums.length;
if (path.size() == n) {
res.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < n; i ++) {
if (visited[i]) {
continue;
}
path.addLast(nums[i]);
visited[i] = true;
dfs(nums, i, visited, path, res);
visited[i] = false;
path.removeLast();
}
}
}
47. 全排列 II
题解:
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
Deque<Integer> path = new ArrayDeque<>();
List<List<Integer>> res = new ArrayList<>();
boolean[] visited = new boolean[nums.length];
Arrays.sort(nums);
dfs(nums, 0, path, visited, res);
return res;
}
private void dfs(int[] nums, int len, Deque<Integer> path, boolean[] visited, List<List<Integer>> res) {
final int n = nums.length;
if (len == n) {
res.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < n; i ++) {
if (visited[i]) {
continue;
}
if (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {
continue;
}
path.addLast(nums[i]);
visited[i] = true;
dfs(nums, len + 1, path, visited, res);
visited[i] = false;
path.removeLast();
}
}
}
37. 解数独
题解:
class Solution {
private int m;
private int n;
private boolean[][] rows;
private boolean[][] cols;
private boolean[][] blocks;
public void solveSudoku(char[][] board) {
this.m = board.length;
this.n = board[0].length;
rows = new boolean[9][10];
cols = new boolean[9][10];
blocks = new boolean[9][10];
for (int i = 0; i < m; i ++) {
for (int j = 0; j < n; j ++) {
if ('.' != board[i][j]) {
char number = board[i][j];
rows[i][number - '0'] = true;
cols[j][number - '0'] = true;
blocks[blockIndex(i, j)][number - '0'] = true;
}
}
}
dfs(board, 0);
}
private boolean dfs(char[][] board, int depth) {
if (depth == 81) {
return true;
}
int row = rowIndex(depth);
int col = colIndex(depth);
if ('.' != board[row][col]) {
return dfs(board, depth + 1);
}
for (int i = 1; i < 10; i ++) {
if (rows[row][i] || cols[col][i] || blocks[blockIndex(row, col)][i]) {
continue;
}
board[row][col] = (char)(i + '0');
rows[row][i] = true;
cols[col][i] = true;
blocks[blockIndex(row, col)][i] = true;
if (dfs(board, depth + 1)) {
return true;
}
rows[row][i] = false;
cols[col][i] = false;
blocks[blockIndex(row, col)][i] = false;
board[row][col] = '.';
}
return false;
}
private int rowIndex(int depth) {
return depth / 9;
}
private int colIndex(int depth) {
return depth % 9;
}
private int blockIndex(int i, int j) {
return i / 3 * 3 + j / 3;
}
}
22. 括号生成
题解:
class Solution {
public List<String> generateParenthesis(int n) {
List<String> res = new ArrayList<>();
dfs("", res, 0, 0, n);
return res;
}
private void dfs(String s, List<String> res, int num, int index, int n) {
if (num > n || index > 2 * n) {
return;
}
if (index == 2 * n && num == n) {
if (checkParenthesis(s)) {
res.add(s);
}
return;
}
dfs(s + "(", res, num + 1, index + 1, n);
dfs(s + ")", res, num, index + 1, n);
}
private boolean checkParenthesis(String s) {
final int n = s.length();
if (0 != (n % 2)) {
return false;
}
Stack<Character> stack = new Stack<>();
for (int i = 0; i < n; i ++) {
char c = s.charAt(i);
if ('(' == c) {
stack.push(c);
} else {
if (stack.isEmpty()) {
return false;
}
stack.pop();
}
}
return stack.isEmpty();
}
}
17. 电话号码的字母组合
题解:
class Solution {
private String[] strs = new String[]{
"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"
};
public List<String> letterCombinations(String digits) {
List<String> res = new ArrayList<>();
if (null == digits || "".equals(digits)) {
return res;
}
dfs("", 0, digits, res);
return res;
}
private void dfs(String s, int depth, String digits, List<String> res) {
final int n = digits.length();
if (depth == n) {
res.add(s);
return;
}
String str = strs[digits.charAt(depth) - '0'];
for (int i = 0; i < str.length(); i ++) {
char c = str.charAt(i);
dfs(s + c, depth + 1, digits, res);
}
}
}
39. 组合总和
题解:
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
Deque<Integer> path = new LinkedList<>();
dfs(candidates, target, 0, 0, path, res);
return res;
}
private void dfs(int[] candidates, int target, int index, int sum, Deque<Integer> path, List<List<Integer>> res) {
final int n = candidates.length;
if (sum == target) {
res.add(new ArrayList<>(path));
return;
}
if (sum > target) {
return;
}
for (int i = index; i < n; i ++) {
path.addLast(candidates[i]);
dfs(candidates, target, i, sum + candidates[i], path, res);
path.removeLast();
}
}
}
40. 组合总和 II
题解:
class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
Deque<Integer> path = new ArrayDeque<>();
boolean[] visited = new boolean[candidates.length];
Arrays.sort(candidates);
dfs(candidates, 0, visited, -1, target, path, res);
return res;
}
private void dfs(int[] candidates, int sum, boolean[] visited, int index, int target, Deque<Integer> path, List<List<Integer>> res) {
if (sum == target) {
res.add(new ArrayList<>(path));
return;
}
if (sum > target) {
return;
}
for (int i = index + 1; i < candidates.length; i ++) {
if (i > 0 && candidates[i] == candidates[i - 1] && !visited[i - 1]) {
continue;
}
path.addLast(candidates[i]);
visited[i] = true;
dfs(candidates, sum + candidates[i], visited, i, target, path, res);
visited[i] = false;
path.removeLast();
}
}
}
216. 组合总和 III
题解:
class Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
Deque<Integer> path = new ArrayDeque<>();
List<List<Integer>> res = new ArrayList<>();
dfs(0, 0, 0, k, n, path, res);
return res;
}
private void dfs(int index, int num, int sum, int k, int n, Deque<Integer> path, List<List<Integer>> res) {
if (num == k && sum == n) {
res.add(new ArrayList<>(path));
return;
}
if (num > k || sum > n) {
return;
}
for (int i = index + 1; i < 10; i ++) {
path.addLast(i);
dfs(i, num + 1, sum + i, k, n, path, res);
path.removeLast();
}
}
}
78. 子集
题解:
class Solution {
public List<List<Integer>> subsets(int[] nums) {
Deque<Integer> path = new ArrayDeque<>();
List<List<Integer>> res = new ArrayList<>();
dfs(nums, -1, path, res);
return res;
}
private void dfs(int[] nums, int index, Deque<Integer> path, List<List<Integer>> res) {
res.add(new ArrayList<>(path));
for (int i = index + 1; i < nums.length; i ++) {
path.addLast(nums[i]);
dfs(nums, i, path, res);
path.removeLast();
}
}
}
90. 子集 II
题解:
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Deque<Integer> path = new ArrayDeque<>();
Arrays.sort(nums);
boolean[] visited = new boolean[nums.length];
dfs(nums, -1, visited, path, res);
return res;
}
private void dfs(int[] nums, int index, boolean[] visited, Deque<Integer> path, List<List<Integer>> res) {
res.add(new ArrayList<>(path));
for (int i = index + 1; i < nums.length; i ++) {
if (visited[i]) {
continue;
}
if (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {
continue;
}
visited[i] = true;
path.addLast(nums[i]);
dfs(nums, i, visited, path, res);
path.removeLast();
visited[i] = false;
}
}
}
1593. 拆分字符串使唯一子字符串的数目最大
题解:
class Solution {
private int res = 1;
public int maxUniqueSplit(String s) {
Set<String> visited = new HashSet<>();
dfs(s, 0, visited);
return res;
}
private void dfs(String s, int sum, Set<String> visited) {
final int n = s.length();
if (0 == n) {
res = Math.max(res, sum);
return;
}
for (int i = 1; i <= n; i ++) {
String preStr = s.substring(0, i);
String postStr = s.substring(i, n);
if (visited.contains(preStr)) {
continue;
}
visited.add(preStr);
dfs(postStr, sum + 1, visited);
visited.remove(preStr);
}
}
}
79. 单词搜索
题解:
class Solution {
private int[][] directions = new int[][]{
{-1, 0}, {0, 1}, {1, 0}, {0, -1}
};
private int m;
private int n;
public boolean exist(char[][] board, String word) {
m = board.length;
n = board[0].length;
boolean[][] visited = new boolean[m][n];
for (int i = 0; i < m; i ++) {
for (int j = 0; j < n; j ++) {
visited[i][j] = true;
if (dfs(board, i, j, visited, word, 0)) {
return true;
}
visited[i][j] = false;
}
}
return false;
}
private boolean dfs(char[][] board, int row, int col, boolean[][] visited, String word, int index) {
if (board[row][col] != word.charAt(index)) {
return false;
}
final int len = word.length();
if (index == len - 1) {
return true;
}
for (int d = 0; d < directions.length; d ++) {
int x = row + directions[d][0];
int y = col + directions[d][1];
if (x < 0 || x >= m || y < 0 || y >= n || visited[x][y]) {
continue;
}
visited[x][y] = true;
if (dfs(board, x, y, visited, word, index + 1)) {
return true;
}
visited[x][y] = false;
}
return false;
}
}
695. 岛屿的最大面积
题解:
class Solution {
private int m;
private int n;
private int[][] directions = new int[][]{
{-1, 0}, {1, 0}, {0, 1}, {0, -1}
};
private int res;
private Integer sum;
public int maxAreaOfIsland(int[][] grid) {
m = grid.length;
n = grid[0].length;
boolean[][] visited = new boolean[m][n];
res = 0;
for (int i = 0; i < m; i ++) {
for (int j = 0; j < n; j ++) {
if (1 == grid[i][j]) {
sum = 1;
visited[i][j] = true;
dfs(grid, i, j, visited);
visited[i][j] = false;
}
}
}
return res;
}
private void dfs(int[][] grid, int row, int col, boolean[][] visited) {
res = Math.max(res, sum);
grid[row][col] = 0;
for (int d = 0; d < directions.length; d ++) {
int x = row + directions[d][0];
int y = col + directions[d][1];
if (x < 0 || x >= m || y < 0 || y >= n || visited[x][y] || 0 == grid[x][y]) {
continue;
}
visited[x][y] = true;
sum ++;
dfs(grid, x, y, visited);
visited[x][y] = false;
}
}
}
417. 太平洋大西洋水流问题
题解:
class Solution {
private int m;
private int n;
private int[][] directions = new int[][]{
{-1, 0}, {1, 0}, {0, -1}, {0, 1}
};
public List<List<Integer>> pacificAtlantic(int[][] heights) {
m = heights.length;
n = heights[0].length;
List<List<Integer>> res = new ArrayList<>();
for (int i = 0; i < m; i ++) {
for (int j = 0; j < n; j ++) {
boolean[][] visited = new boolean[m][n];
visited[i][j] = true;
if (pacificDfs(heights, i, j, visited) && atlanticDfs(heights, i, j, visited)) {
List<Integer> list = new ArrayList<>();
list.add(i);
list.add(j);
res.add(list);
}
visited[i][j] = false;
}
}
return res;
}
private boolean pacificDfs(int[][] heights, int row, int col, boolean[][] visited) {
for (int d = 0; d < directions.length; d ++) {
int x = row + directions[d][0];
int y = col + directions[d][1];
if (x < 0 || y < 0) {
return true;
}
if (x >= m || y >= n || visited[x][y] || heights[x][y] > heights[row][col]) {
continue;
}
visited[x][y] = true;
boolean flag = pacificDfs(heights, x, y, visited);
visited[x][y] = false;
if (flag) {
return true;
}
}
return false;
}
private boolean atlanticDfs(int[][] heights, int row, int col, boolean[][] visited) {
for (int d = 0; d < directions.length; d ++) {
int x = row + directions[d][0];
int y = col + directions[d][1];
if (x >= m || y >= n) {
return true;
}
if (x < 0 || y < 0 || visited[x][y] || heights[x][y] > heights[row][col]) {
continue;
}
visited[x][y] = true;
boolean flag = atlanticDfs(heights, x, y, visited);
visited[x][y] = false;
if (flag) {
return true;
}
}
return false;
}
}
1020. 飞地的数量
题解:
class Solution {
private int m;
private int n;
private int[][] directions = new int[][]{
{-1, 0}, {1, 0}, {0, -1}, {0, 1}
};
public int numEnclaves(int[][] grid) {
m = grid.length;
n = grid[0].length;
boolean[][] visited = new boolean[m][n];
for (int i = 0; i < m; i ++) {
for (int j = 0; j < n; j ++) {
if ((0 == i || (m - 1 == i) || 0 == j || (n - 1 == j)) && (1 == grid[i][j])) {
dfs(grid, i, j, visited);
}
}
}
int sum = 0;
for (int i = 0; i < m; i ++) {
for (int j = 0; j < n; j ++) {
if (1 == grid[i][j]) {
sum ++;
}
}
}
return sum;
}
private void dfs(int[][] grid, int row, int col, boolean[][] visited) {
grid[row][col] = 0;
for (int d = 0; d < directions.length; d ++) {
int x = row + directions[d][0];
int y = col + directions[d][1];
if (x < 0 || x >= m || y < 0 || y >= n || visited[x][y] || 0 == grid[x][y]) {
continue;
}
visited[x][y] = true;
dfs(grid, x, y, visited);
visited[x][y] = false;
}
}
}
1254. 统计封闭岛屿的数目
题解:
class Solution {
private int m;
private int n;
private int[][] directions = new int[][]{
{-1, 0}, {0, -1}, {1, 0}, {0, 1}
};
public int closedIsland(int[][] grid) {
m = grid.length;
n = grid[0].length;
boolean[][] visited = new boolean[m][n];
for (int i = 0; i < m; i ++) {
for (int j = 0; j < n; j ++) {
if ((0 == i || (m - 1 == i) || 0 == j || (n - 1 == j)) && 0 == grid[i][j]) {
visited[i][j] = true;
dfs(grid, i, j, visited);
visited[i][j] = false;
}
}
}
int res = 0;
for (int i = 0; i < m; i ++) {
for (int j = 0; j < n; j ++) {
if (0 == grid[i][j]) {
res ++;
visited[i][j] = true;
dfs(grid, i, j, visited);
visited[i][j] = false;
}
}
}
return res;
}
private void dfs(int[][] grid, int row, int col, boolean[][] visited) {
grid[row][col] = 1;
for (int d = 0; d < directions.length; d ++) {
int x = row + directions[d][0];
int y = col + directions[d][1];
if (x < 0 || x >= m || y < 0 || y >= n || visited[x][y] || 1 == grid[x][y]) {
continue;
}
visited[x][y] = true;
dfs(grid, x, y, visited);
visited[x][y] = false;
}
}
}
面试题13. 机器人的运动范围
总结:不需要回溯
题解:
class Solution {
private int[][] directions = new int[][]{
{-1, 0}, {1, 0}, {0, -1}, {0, 1}
};
private int res = 0;
public int movingCount(int m, int n, int k) {
boolean[][] visited = new boolean[m][n];
visited[0][0] = true;
dfs(0, 0, m, n, k, visited);
return res;
}
private void dfs(int row, int col, int m, int n, int k, boolean[][] visited) {
if (checkNumber(row) + checkNumber(col) > k) {
return;
}
res ++;
for (int d = 0; d < directions.length; d ++) {
int x = row + directions[d][0];
int y = col + directions[d][1];
if (x < 0 || x >= m || y < 0 || y >= n || visited[x][y]) {
continue;
}
visited[x][y] = true;
dfs(x, y, m, n, k, visited);
}
}
private int checkNumber(int number) {
int sum = 0;
while (number > 0) {
sum += (number % 10);
number = number / 10;
}
return sum;
}
}

这篇博客详细解析了如何使用回溯算法解决LeetCode上的多个经典问题,包括N皇后、全排列、解数独、括号生成等,并提供了题解,最后总结了在哪些情况下不需要使用回溯算法。
1004

被折叠的 条评论
为什么被折叠?



