LeetCode:332.重新安排行程
1.思路
创建结果集res,用于存储路径path
对车程tickets的目的地依次进行排序,path收集首个机场JFK,标记数组used[]跟踪目的机场是否使用
backtracing()回溯
返回结果集
2.代码实现
1class Solution {
2
3 LinkedList<String> res; // 存放结果
4 LinkedList<String> path = new LinkedList<>(); // 存放路径
5
6 public List<String> findItinerary(List<List<String>> tickets) {
7 Collections.sort(tickets, (a, b) -> a.get(1).compareTo(b.get(1))); // 将票程目的机场进行排序,
8 path.add("JFK"); // 起始机场"JFK"
9 boolean[] used = new boolean[tickets.size()]; //标记数组:跟踪机票是否使用
10 backtracking((ArrayList) tickets, used); // 开始回溯过程 为什么进行强转?猜测是便于对ArrayList方法的调用?
11 return res; // 返回结果
12 }
13
14 public boolean backtracking(ArrayList<List<String>> tickets, boolean[] used) {
15 if (path.size() == tickets.size() + 1) { // 一个车程tickets两个节点,2车程3个机场节点
16 res = new LinkedList(path); // 将当前路径存储为结果
17 return true; // 表示成功完成回溯
18 }
19
20 for (int i = 0; i < tickets.size(); i++) {
21 if (!used[i] && tickets.get(i).get(0).equals(path.getLast())) { // 如果机票未使用且起始机场与路径中的最后一个机场匹配
22 path.add(tickets.get(i).get(1)); // 将目的机场加入路径中
23 used[i] = true; // 标记机票已使用
24
25 if (backtracking(tickets, used)) { // 递归探索下一张机票
26 return true; // 如果找到有效的行程,返回true
27 }
28
29 used[i] = false; // 标记机票未使用,以便其他可能的路径使用
30 path.removeLast(); // 从路径中移除最后一个机场
31 }
32 }
33 return false; // 当前路径没有找到有效的行程
34 }
35}
LeetCode:51. N皇后
1.思路
二维数组中寻找符合条件的result,for循环横向遍历,backtracking()纵向遍历,直到输出结果或遍历结束.
二维系统中建立坐标系,模拟皇后位置写出排除"同行同列同45°的"的条件,用于筛选结果,建立坐标系的原点非常重要,决定了具体的实现细节.
2.代码实现
1class Solution {
2 List<List<String>> res = new ArrayList<>(); // 存储最终的结果
3
4 public List<List<String>> solveNQueens(int n) {
5 char[][] chessboard = new char[n][n]; // 创建一个n*n的二维字符数组
6 for (char[] c : chessboard) {
7 Arrays.fill(c, '.');
8 }
9 // for (int i = 0; i < chessboard.length; i++) {
10 // for (int j = 0; j < chessboard[i].length; j++) {
11 // // 对二维数组的每个元素进行操作
12 // chessboard[i][j] = '.';
13 // // 其他操作...
14 // }
15 // }
16 backtracking(n, 0, chessboard);
17 return res;
18 }
19 public void backtracking(int n, int row, char[][] chessboard) {
20 if (row == n) {
21 res.add(Array2List(chessboard));
22 return;
23 }
24 for (int col = 0; col < n; col++) {
25 if (isValid(row, col, n, chessboard)) {
26 chessboard[row][col] = 'Q';
27 backtracking(n, row + 1, chessboard);
28 chessboard[row][col] = '.';
29 }
30 }
31 }
32
33 public List Array2List(char[][] chessboard) {
34 List<String> list = new ArrayList<>();
35 for (char[] c : chessboard) {
36 list.add(String.copyValueOf(c));
37 }
38 return list;
39 }
40
41 public boolean isValid(int row, int col, int n, char[][] chessboard) {
42 // 检查列
43 for (int i = 0; i < row; i++) {
44 if (chessboard[i][col] == 'Q') {
45 return false;
46 }
47 }
48 for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
49 if (chessboard[i][j] == 'Q') {
50 return false;
51 }
52 }
53 // 检查135度对角线
54 for (int i = row -1, j = col + 1; i >= 0 && j <= n - 1; i--, j++) {
55 if (chessboard[i][j] == 'Q') {
56 return false;
57 }
58 }
59 return false;
60 }
61}
LeetCode:37. 解数独
1.思路
两层for循环嵌套递归函数,外设一个行列及九宫格是否有效性判断的函数
2.代码实现
1class Solution {
2
3 public void solveSudoku(char[][] board) {
4 solveSudokuHelper(board);
5 }
6
7 // 回溯函数
8 public boolean solveSudokuHelper(char[][] board) {
9 for (int i = 0; i < 9; i++) { // 遍历行
10 for (int j = 0; j < 9; j++) { // 遍历列
11 if (board[i][j] != '.') { // 跳过数字
12 continue;
13 }
14 // 为空白处赋予数字字符
15 for (char k = '1'; k <= '9'; k++) {
16 if (isValidSudoku(i, j, k, board)) { // 判断行列是否有效
17 board[i][j] = k; // 有效则赋值
18 if (solveSudokuHelper(board)) { // 找到一个符合条件的结果立刻返回true
19 return true;
20 }
21 board[i][j] = '.'; // 无效则回溯,剪枝操作
22 }
23 }
24
25 return false; // 如果该节点九个数都不满足要求,返回false
26 }
27 }
28 return true; // 最后找到返回true
29 }
30
31 public boolean isValidSudoku(int row, int col, char val, char[][] board) {
32 for (int i = 0; i < 9; i++) {
33 if (board[row][i] == val) {
34 return false;
35 }
36 }
37 for (int j = 0; j < 9; j++) {
38 if (board[j][col] == val) {
39 return false;
40 }
41 }
42 // 9宫格内去重
43 int startRow = (row / 3) * 3;
44 int startCol = (col / 3) * 3;
45 for (int i = startRow; i < startRow + 3; i++) {
46 for (int j = startCol; j < startCol + 3; j++) {
47 if (board[i][j] == val) {
48 return false;
49 }
50 }
51 }
52 return true;
53 }
54}
总结
组合问题:for循环横向遍历,递归实现纵向遍历
分割问题
排列问题
解数独、N皇后问题
真难,先这样~