暴力递归
问:
- 假设有N * N 的棋盘,要放置N个皇后棋子,要求所有棋子不能同行、不能同列、不能同对角线。求一共有多少种放置的方案。N皇后问题。
- 汉诺塔问题。
解:
- 声明一个数组,下标表示行,值表示列。从第0行开始,遍历每一个列,判断这一列是否可放置皇后,若可以,就在这一条件下递归下一行,直到最后一行就是一种放置方案。
function nQueen(n) {
if (n < 1) return 0
// 记录棋子位置
const positionRecord = []
function recursion(curRow, positionRecord, n) {
// 最后一行,表明这是一种可行方案,返回1
if (curRow === n) return 1
let res = 0
// 判断当前行有哪些列可以放
for (let j = 0; j < n; j++) {
if (isRight(positionRecord, curRow, j)) {
// 若可以放置,就记录当前行的棋子位置
positionRecord[curRow] = j
res += recursion(curRow + 1, positionRecord, n)
}
}
return res
}
// 判断是否可放
function isRight(positionRecord, curRow, col) {
for (let i = 0; i < curRow; i++) {
// 同列,同斜线就不可放置
if (col === positionRecord[i] || Math.abs(positionRecord[i] - col) === Math.abs(i - curRow)) return false
}
return true
}
// 从第0行开始放皇后
return recursion(0, positionRecord, n)
}
- 假设有5个盘子,要移动第五个盘子到end柱子上,可以推断出首先要移动前四个盘子到other柱子上,然后把第五个盘子移动到end上之后再把前四个盘子移动到end柱子上。局部过程符合要求,那么递归的全局也符合要求。
function hanoi(current, start, end, other) {
// 当前是第一个盘子,直接移动到end柱子上
if (current === 1) {
console.log(`${current}的盘子从${start}到${end}`);
return
}
// 把当前盘子的上面盘子移动到other柱子上
hanoi(current -1, start, other, end)
console.log(`${current}的盘子从${start}到${end}`);
// 再把当前盘子上面的盘子移动到end柱子上
hanoi(current - 1, other, end, start)
}
hanoi(3, '左', '右', '中')