LeetCode习题:汉诺塔问题

该博客讨论了经典的汉诺塔问题,介绍了如何利用栈数据结构和递归算法将所有盘子从第一根柱子移动到最后一根柱子。解题过程中详细解释了解题思路和步骤,并给出了Swift代码实现。同时,分析了算法的时间复杂度为O(2^n)和空间复杂度为O(n)

题目描述:在经典汉诺塔问题中,有 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]
提示:A中盘子的数目不大于14个。
解题思路:通过纸和笔进行实际的“搬运”工作
1. A盘中数目为0,无需搬运, 操作步数为:0(2^0 - 1)
2. A盘中数目为1,A->C,操作步数为:1(2^1-1)
3. A盘中数目为2,需要将A盘中最上面的圆盘先放入B柱,然后将A盘中底部大圆盘放入C,然后再将B中的小圆盘放入C即完成,即 A->B, A->C, B->C, 操作步数为:3(2^2-1)
4. 同理,A盘中数目为3时,A->C, A->B, C->B, A->C, B->A, B->C, A->C, 操作步数为:7(2^3-1)
...
通过以上步骤我们发现,回顾整个搬运过程,如果想将n个从小到大排列的圆盘从A柱搬运到C柱,并且保持排列顺序不变,需要先将A柱上面的n-1个圆盘经过C柱的搬运到B柱上,也就是说,将A柱最大圆盘搬运到C柱的时候,此时B柱上是从小到大排列的n-1个圆盘,即可以将A柱最大圆盘搬运到C柱的时刻,三根柱子的情况是:A柱剩最大圆盘,B柱n-1圆盘(从小到大排列),C柱为空,这样就可以想象成: A(n-1)->B, A->C, B->C,其中A(n-1)->B过程需要经过C柱, B->C过程需要经过A柱
解题语言: Swift
class Solution {
    func hanota(_ A: inout [Int], _ B: inout [Int], _ C: inout [Int]) {
        let n = A.count
        recursion(&A, &B, &C, n)
    }

    func recursion(_ A: inout [Int], _ B: inout [Int], _ C: inout [Int], _ n: Int) {
        if n <= 0 {
            return
        }
        if n == 1 {
            let val = A.removeLast()
            C.append(val)
            return
        }
        //将A上面的 n-1 个圆盘经由 C 移到 B
        recursion(&A, &C, &B, n - 1)
        //将A最底部的盘移动到C
        let val = A.removeLast()
        C.append(val)
        //将B上面的 n-1 个圆盘经 A 移动到 C
        recursion(&B, &A, &C, n - 1)
    }
}
复杂度分析:
时间复杂度:O(2n),其中n为圆盘数目,因为将n个圆盘从A->C需要经过2n-1步
空间复杂度: O(n), 其中n为圆盘数目,空间复杂度主要取决于递归调用的栈空间,因为递归需要保存调用栈,直至递归完成,递归最大深度为n,
题目来源:LeetCode
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值