Leetcode 刷题 回溯算法

文章介绍了如何使用Collections.sort进行列表排序,以及在解决N皇后问题、重新安排行程和解数独等经典回溯法问题中的应用。通过排序机票,建立路径,并用回溯法搜索解决方案,找到皇后在棋盘上的合法位置和数独的解答。
摘要由CSDN通过智能技术生成

332. 重新安排行程

字母序靠前排在前面 如何记录映射关系 这是我不会的点

Collections.sort(tickets, (a,b)->a.get(1).compareTo(b.get(1)));

Collections.sort()方法详解

是对数据进行排序的一个方法,根据指定比较器产生的顺序对指定列表进行排序。

Collections.sort() 排序
返回值:return a.compareTo(b) 就排序了,为什么呢?
compareTo() 这个方法,它返回了3种int类型的值:
    负整数 : a < b,a排在前面
    零 : a = b, 位置不变
    正整数 : a > b, a排在后面

剩下的就简单了

需要一个used数组来判断是否选中tickets

class Solution {

    private LinkedList<String> path = new LinkedList<>();
    private LinkedList<String> res;
 
    public List<String> findItinerary(List<List<String>> tickets) {
        Collections.sort(tickets, (a,b)->a.get(1).compareTo(b.get(1)));
        path.add("JFK");
        boolean[] used = new boolean[tickets.size()];
        backtracking(tickets, used);
        return res;
    }

    private boolean backtracking(List<List<String>> tickets, boolean[] used){
        if(path.size() == tickets.size() + 1){
            res = new LinkedList<>(path);
            return true;
        }

        for(int i = 0; i < tickets.size(); i++){
            if(!used[i] && tickets.get(i).get(0).equals(path.getLast())){
                path.add(tickets.get(i).get(1));
                used[i] = true;
                if (backtracking(tickets, used)) {
                    return true;
                }
                used[i] = false;
                path.removeLast();
            }
        }
         return false;
    }
}

51. N 皇后

第一次做这种棋盘的题目

一开始不知道怎么构建一个棋盘

其实就是一个二维数组

char[][] chessboard = new char[n][n];
for(char[] c : chessboard){
    Arrays.fill(c, '.');
}

 

可以看出,二维矩阵中矩阵的高就是这棵树的高度,矩阵的宽就是树形结构中每一个节点的宽度。 

只要搜索到了树的叶子节点,说明就找到了皇后们的合理位置了

棋盘的宽度就是for循环的长度,递归的深度就是棋盘的高度,这样就可以套进回溯法的模板里了

回顾

String.copyValueOf(c);

copyValueOf()方法返回表示字符数组字符的String 此方法返回一个新的String数组并将字符复制到其中。

static String copyValueOf(char[] data, int offset, int  count)
class Solution {
    List<List<String>> res = new ArrayList<>();

    public List<List<String>> solveNQueens(int n) {
        char[][] chessboard = new char[n][n];
        for(char[] c : chessboard){
            Arrays.fill(c, '.');
        }
        backtracking(n, 0, chessboard);
        return res;
    }

    private void backtracking(int n, int row, char[][] chessboard){
        if(row == n){
            res.add(ArrayList2List(chessboard));
            return;
        }

        for(int col = 0; col < n; col++){
            if(isValid(n, row, col, chessboard)){
                chessboard[row][col] = 'Q';
                backtracking(n, row+1, chessboard);
                chessboard[row][col] = '.';
            }  
        }
    }

    private List ArrayList2List(char[][] chessboard){
        List<String> list = new ArrayList<>();
        for(char[] c : chessboard){
            list.add(String.copyValueOf(c));
        }
        return list;
    }

    private boolean isValid(int n, int row, int col, 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 ; i--, j++){
            if(chessboard[i][j] == 'Q'){
                return false;
            }
        }
        return true;
    }
}

37. 解数独

其实就是遍历棋盘的每一行每一列

当遇到需要填写数字的时候

从1到9选择一个数字 并且判断合法性 然后填入

最终返回棋盘即可

 这里递归函数需要返回值

递归函数的返回值需要是bool类型

 因为解数独找到一个符合的条件(就在树的叶子节点上)立刻就返回,相当于找从根节点到叶子节点一条唯一路径,所以需要使用bool返回值。

一个for循环遍历棋盘的行,一个for循环遍历棋盘的列,一行一列确定下来之后,递归遍历这个位置放9个数字的可能性!

class Solution {
    public void solveSudoku(char[][] board) {
        backtracking(board);
    }

    private boolean backtracking(char[][] board){
        for(int i = 0; i < 9; i++){
            for(int j = 0; j < 9; j++){
                if(board[i][j] != '.'){
                    continue;
                }
                for(char c = '1'; c <= '9'; c++){
                    if(isValid(i, j, c, board)){
                        board[i][j] = c;
                        if(backtracking(board)){
                            return true;
                        }
                        board[i][j] = '.';
                    }
                }
                return false;
            }
        }
        return true;
    }

    private boolean isValid(int row, int col, char c, char[][] board){
        for(int i = 0; i < 9; i++){
            if(board[row][i] == c){
                return false;
            }
        }

        for(int i = 0; i < 9; i++){
            if(board[i][col] == c){
                return false;
            }
        }
        int startRow = (row / 3) * 3;
        int startCol = (col / 3) * 3;
        for(int i = 0; i < 3; i++){
            for(int j = 0; j < 3; j++){
                if(board[startRow + i][startCol + j] == c){
                    return false;
                }
            }
        }
        return true;
    }
}

9宫格的判断需要学习一下 

// 9宫格里是否重复
int startRow = (row / 3) * 3;
int startCol = (col / 3) * 3;
for (int i = startRow; i < startRow + 3; i++){
    for (int j = startCol; j < startCol + 3; j++){
         if (board[i][j] == val){
             return false;
         }
    }
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值