算法练习day26

69 阅读2分钟

一、重新安排行程

出发地和目的地可能是相同,所以需要去重

/**
 * @param {string[][]} tickets
 * @return {string[]}
 */
var findItinerary = function(tickets) {
    let result = ['JFK']
    let map = {}

    for (const tickt of tickets) {
        const [from, to] = tickt
        if (!map[from]) {
            map[from] = []
        }
        map[from].push(to)
    }

    for (const city in map) {
        // 对到达城市列表排序
        map[city].sort()
    }
    function backtracing() {
        if (result.length === tickets.length + 1) {
            return true
        }
        if (!map[result[result.length - 1]] || !map[result[result.length - 1]].length) {
            return false
        }
        for(let i = 0 ; i <  map[result[result.length - 1]].length; i++) {
            let city = map[result[result.length - 1]][i]
            // 删除已走过航线,防止死循环
            map[result[result.length - 1]].splice(i, 1)
            result.push(city)
            if (backtracing()) {
                return true
            }
            result.pop()
            map[result[result.length - 1]].splice(i, 0, city)
        }
    }
    backtracing()
    return result

};
/**
 * @param {string[][]} tickets
 * @return {string[]}
 */
var findItinerary = function (tickets) {
    let result = ['JFK']
    let map = {}

    for (const tickt of tickets) {
        const [from, to] = tickt
        if (!map[from]) {
            map[from] = [{ city: to, used: false }]
        } else {
            map[from].push({ city: to, used: false })
        }
    }

    for (const city in map) {
        // 对到达城市列表排序
        map[city].sort((x, y) =>{
            if( x.city < y.city ) {
                return -1
            } else if(x.city < y.city) {
                return 1
            } else {
                return 0
            }
        })
    }
    function backtracing() {
        if (result.length === tickets.length + 1) {
            return true
        }
        let lastCity = result[result.length - 1]
        if (!map[lastCity] || !map[lastCity].length) {
            return false
        }
        for (let i = 0; i < map[lastCity].length; i++) {
            let curCity = map[lastCity][i]
            if (!curCity.used) {
                // 删除已走过航线,防止死循环
                curCity.used = true
                result.push(curCity.city)
                if (backtracing()) {
                    return true
                }
                result.pop()
                curCity.used = false
            }

        }
    }
    backtracing()
    return result

};

二、N皇后

每一行确定Q的位置,终止条件为row===n

/**
 * @param {number} n
 * @return {string[][]}
 */
var solveNQueens = function(n) {
    let result = []
    let chessboard = new Array(n).fill(0).map(_ => new Array(n).fill('.'))
    function backtracking(row) {
        if(row === n) {
            result.push(chessboard.map(item => item.join('')))
            return
        }
        for(let col = 0; col < n;col++) {
            if(isValid(row, col, chessboard)) {
                chessboard[row][col] = 'Q'
                backtracking(row + 1)
                chessboard[row][col] = '.'
            }
        }
    }
    function isValid(row, col, chessboard) {
        for(let i = 0;i < row;i++) {
            if(chessboard[i][col] === 'Q') {
                return false
            }
        }
        let i = row- 1
        let j = col - 1
        while(i >=0 && j >= 0){
            if(chessboard[i][j] === 'Q') {
                return false
            }
            i--
            j--
        }
        i = row - 1
        j = col + 1
        while(i >=0 && j < n){
            if(chessboard[i][j] === 'Q') {
                return false
            }
            i--
            j++
        }
        return true
    }
    backtracking(0)
    return result
};

三、解数独

相比于N皇后,数独问题需要双重循环递归

/**
 * @param {character[][]} board
 * @return {void} Do not return anything, modify board in-place instead.
 */
var solveSudoku = function(board) {
    function backtracking() {
        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 < 10;k++) {
                        let val = String(k)
                        if(isValid(i, j, val, board)) {
                            board[i][j] = val
                            if(backtracking()) {
                                return true
                            }
                            board[i][j] = '.'
                        }
                    }
                    return false
                }
            }
        }
        return true
    }
    function isValid(row, col, val, board) {
        for(let i = 0; i < 9;i++) {
            if(board[row][i] === val) {
                return false
            }
        }
        for(let i = 0; i < 9;i++) {
            if(board[i][col] === val) {
                return false
            }
        }
        let startRow = Math.floor(row / 3) * 3
        let startCol = Math.floor(col / 3) * 3
        for(let i = startRow; i < startRow + 3; i++) {
            for(let j = startCol; j < startCol + 3; j++) {
                if(board[i][j] === val) {
                    return false
                }
            }
        }
        return true
    }
    backtracking()
    return board
};