代码随想录算法训练营Day 30|332. 重新安排行程、51. N 皇后、37. 解数独

73 阅读2分钟

332. 重新安排行程

题目链接

思路

先跳过



51. N 皇后

题目链接

要求:按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 **n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位

思路

var solveNQueens = function(n) {
    let chessboard = new Array(n).fill([]).map(()=>new Array(n).fill('.'))
    let res = []
    backstracking(chessboard, n, 0)
    return res
    function transform(chessboard){
        let newChessboard = []
        chessboard.forEach(row => {
            let rowStr = ''
            row.forEach(value => {
                rowStr += value
            })
            newChessboard.push(rowStr)
        })
        return newChessboard
    }
    function backstracking(chessboard, n, row){
        if(row == n){
            res.push(transform(chessboard))
            return
        }
        for(let i=0; i<n; i++){
            if(isValid(chessboard, n, row, i)){
                chessboard[row][i] = 'Q'
                backstracking(chessboard, n, row+1)
                chessboard[row][i] = '.'
            }
        }
    }
    function isValid(chessboard, n, row, col){
        //不同列  行不需要判断,在for循环的时候已经不会同行
        for(let i=0; i<row; i++){
            if(chessboard[i][col] == 'Q'){
                return false
            }
        }
        //45度 
        for(let i=row-1, j=col-1; i>=0 && j>=0; i--, j--){
            if(chessboard[i][j] == 'Q'){
                return false
            }
        }
        for(let i=row-1, j=col+1; i>=0 && j<=n; i--, j++){
            if(chessboard[i][j] == "Q"){
                return false
            }
        }
        return true
    }
};

37. 解数独

题目链接

要求:编写一个程序,通过填充空格来解决数独问题。

数独的解法需 遵循如下规则

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

数独部分空格内已填入了数字,空白格用 '.' 表示。

思路

两层for循环+递归函数

判断棋盘是否合法有如下三个维度:

  • 同行是否重复
  • 同列是否重复
  • 9宫格里是否重复
/**
 * @param {character[][]} board
 * @return {void} Do not return anything, modify board in-place instead.
 */
var solveSudoku = function(board) {
    return backstracking(board)
    function backstracking(board){
        for(let i=0; i<board.length; i++){ //遍历行
            for(let j=0; j<board[0].length; j++){ //遍历列
                if(board[i][j] == '.'){
                    for(let k = 1; k<=9; k++){ // (i, j) 这个位置放k是否合适
                        if(isValid(board, i, j, `${k}`)){
                            board[i][j] = `${k}`
                            if(backstracking(board)) return true
                            board[i][j] = '.'
                        }
                    }
                    // 9个数都试完了,都不行,那么就返回false
                    return false
                }
            }
        }
        return true
    }

    function isValid(board, row, col, val){
        for(let i=0; i<9; i++){ //同行是否重复
            if(board[row][i] == val){
                return false
            }
        } 
        for(let j=0; j<9; j++){ //同列是否重复
            if(board[j][col] == val){
                return false
            }
        }
        //判断九宫格是否重复
        let statrRow = Math.floor(row/3) * 3 //第几个九宫格
        let startCol = Math.floor(col/3) * 3
        for(let i=statrRow; i<statrRow+3; i++){
            for(let j=startCol; j<startCol+3; j++){
                if(board[i][j] == val){
                    return false
                }
            }
        }
        return true
    }
};