一、重新安排行程
出发地和目的地可能是相同,所以需要去重
/**
* @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
};