算法学习记录(十六)

119 阅读1分钟

暴力递归

问:

  1. 假设有N * N 的棋盘,要放置N个皇后棋子,要求所有棋子不能同行、不能同列、不能同对角线。求一共有多少种放置的方案。N皇后问题。
  2. 汉诺塔问题。

解:

  1. 声明一个数组,下标表示行,值表示列。从第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)
}
  1. 假设有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, '左', '右', '中')