LeetCode 算法:汉诺塔问题

678 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 6 天,点击查看活动详情

汉诺塔问题

原题地址

在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制: (1) 每次只能移动一个盘子; (2) 盘子只能从柱子顶端滑出移到下一根柱子; (3) 盘子只能叠在比它大的盘子上。

请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子。

你需要原地修改栈。

示例1:

输入:A = [2, 1, 0], B = [], C = []
输出:C = [2, 1, 0]

示例2:

输入:A = [1, 0], B = [], C = []
输出:C = [1, 0]

示例3:

输入:A = [5, 2, 0], B = [], C = []
输出:C = [5, 2, 0]

提示:

  • A中盘子的数目不大于14个。

思路分析

  1. 使用递归的方式来解决,如果想使 A 中的盘子都移动到 C 中,那么首先将 A 中的 n-1 个移动到 B,然后将 A 中剩余一个的移动到 C,然后再将 B 中的 n-1 个移动到 C
  2. 等到 A 中剩余 1 个时,将 A 中的直接移到 C 即可;
  3. 定义一个 move 方法,接收 (len, A, B, C) 的入参,表示将 A 中的 len 个以 B 做中介移动到 C 中;
  4. 那么,按照步骤1、2的描述,若 len === 1 时,直接移动到 C 上即可;
  5. 否则,需要将 A 中的 len-1 个移动到 B,即 move(len - 1, A, C, B);然后将 A 剩余的一个移动到 C,即 C.push(A.pop());然后将 B 中的 len-1 个移动到 C,即 move(len - 1, B, A, C)即可;
  6. 最后调用 move 方法, 即 move(len, A, B, C)

AC 代码

/**
 * @param {number[]} A
 * @param {number[]} B
 * @param {number[]} C
 * @return {void} Do not return anything, modify C in-place instead.
 */
var hanota = function(A, B, C) {
    const len = A.length
    // 将A中的n个移动到C
    const move = (len, A, B, C) => {
        if (len === 1) {
            C.push(A.pop())
            return
        }
        // 将A中的n-1个移动到B
        move(len - 1, A, C, B)
        // 将A剩余的一个移动到C
        C.push(A.pop())
        // 将B中的n-1个移动到C
        move(len - 1, B, A, C)
    }
    move(len, A, B, C)
};

结果:

  • 执行结果: 通过
  • 执行用时:52 ms, 在所有 JavaScript 提交中击败了95.05%的用户
  • 内存消耗:41.1 MB, 在所有 JavaScript 提交中击败了14.85%的用户
  • 通过测试用例:14 / 14

END