算法修炼Day30|332.重新安排行程 ● 51. N皇后 ● 37. 解数独

55 阅读1分钟

LeetCode:332. 重新安排行程 - 力扣(LeetCode)

1.思路

首先进行排序,将目的地址字符数值较小的排在前面优先考虑,这是排序的意义。 回溯方法参数;中止条件;确定单层递归的逻辑

2.代码实现
class Solution {
    List<String> res = new ArrayList<>();
    List<String> path = new ArrayList<>();
    
    public List<String> findItinerary(List<List<String>> tickets) {
        Collections.sort(tickets, (a, b) -> a.get(1).compareTo(b.get(1))); // 按目的地排序
        path.add("JFK"); // 起始点为"JFK"
        boolean[] used = new boolean[tickets.size()]; // 记录每张机票是否被使用过
        backTracking(tickets, used); // 回溯算法寻找行程
        return res; // 返回最终的行程结束
    }
    public boolean backTracking(List<List<String>> tickets, boolean[] used) {
        if (path.size() == tickets.size() + 1) { // 如果路径长度等于机票数量加1,说明找到了一条合法行程
            res = new ArrayList<>(path); // 将当前路径保存到结果变量中
            return true; // 返回true,表示已经找到了合法行程
        }
        // 遍历所有机票
        for (int i = 0; i < tickets.size(); i++) {
            if (!used[i] && tickets.get(i).get(0).equals(path.get(path.size() - 1))) { // 如果当前路径没有被使用且当前路径的起始路径等于path中的最后一个节点
                path.add(tickets.get(i).get(1)); // 将目的路径加入到路径中
                used[i] = true; // 标记该机票已经被使用
                if (backTracking(tickets, used)) { // 递归
                    return true;
                } 
                used[i] = false; // 如果没有找到合法行程,回溯,将该机票标记为未使用
                path.remove(path.size() - 1); // 将目的地从路径中移除
            }
        }
        return false; // 如果遍历完所有机票都没有找到合法行程,返回false
    }
}

LeetCode:

1.思路

抄了一遍又一遍。。

2.代码实现
class Solution {
    List<List<String>> res = new ArrayList<>();

    public List<List<String>> solveNQueens(int n) {
        char[][] chessboard = new char[n][n]; // 创建一个 n x n 的期盼
        for (char[] c : chessboard) {
            Arrays.fill(c, '.'); // 初始化棋盘
        }
        backTrack(n, 0, chessboard); // 回溯算法求解 N 皇后问题
        return res;
    }
    public void backTrack(int n, int row, char[][] chessboard) {
        // 中止条件
        if (row == n) { // 如果已经遍历完所有行,将当前棋盘状态添加到结果列表中
            res.add(Array2List(chessboard));
            return;
        }

        for (int col = 0; col < n; col++) { // 遍历当前行的每一列
            if (isValid(row, col, n, chessboard)) { // 判断当前位置是否可以放置皇后
                chessboard[row][col] = 'Q'; // 放置皇后
                backTrack(n, row + 1, chessboard); // 继续递归处理下一行
                chessboard[row][col] = '.'; // 回溯,将当前位置恢复为 '.'
            }
        }
    }

    public List Array2List(char[][] chessboard) {
        List<String> list = new ArrayList<>(); // 用于存储每个棋盘状态的列表

        for (char[] c : chessboard) {
            list.add(String.copyValueof(c)); // 将每一行转换为字符串,并添加到列表中
        }
        return list; // 返回存储棋盘状态的列表
    }

    public boolean isValid(int row, int col, int n, char[][] chessboard) {
        // 检查当前行是否有皇后
        for (int i = 0; i < row; i++) { 
            if (chessboard[i][col] == 'Q') {
                return false;
            }
        }

        // 检查左上方是否有皇后
        for (int i = row - 1, j = col - 1; i >= 0&& j >= 0; i--, j--) {
            if (chessboard[i][j] == 'Q') {
                return false;
            }
        }

        // 检查右上方是否有皇后
        for (int i = row - 1, j = col + 1; i >= 0 && j <= n - 1; i--, j++) {
            if (chessboard[i][j] == 'Q') {
                return false;
            }
        }
        return true;
    }
}