算法题 - 汉诺塔问题 - Python

问题描述:

汉诺塔问题

汉诺塔传说,有三根柱子可以用大写字母ABC命名,其中只有A柱子摆放n片圆盘(1<=n<=64), 若要把A柱子上的所有圆盘转移到 C柱子上,问最少需要移动多少次圆盘?

移动圆盘的规则如下:

  1. 每次只能移动一片圆盘
  2. 任何情况下,大的圆盘必须摆放在小的圆盘之

问题分析:

昨天baidu校招一面碰到的题目,问了其他同学,基本上一面都是以基础的数据结构题目为主,现在总结一下。问题估计是经典的不能在经典了,递归解决,这个题目对于递归的理解还是比较深刻。当时问了两个问题:1,是求出移动次数;2,输出每一步移动的情况。个人感觉对这类问题,重在理解

递归解决,具体步骤如下:

(1)设 Hanoi(n, A, B, C) 表示,把A中的n个圆盘,通过中间媒介B,移动到C。现在思考如何分解Hanoi(n, A, B, C)

  1. 要想把A中的n个圆盘,移动到C,一定会经过什么操作?

  2. 第一步:一定会先把A中上面的n-1圆盘移动到B, 这个过程中C一定是中间媒介。

  3. 第二步:然后,把A中剩下的最大的一个圆盘(也就是最下面那个圆盘)移动到C

  4. 第三步:最后,把B中所有的n-1过个圆盘移动到C, 很显然,现在A一定是中间媒介。

  5. 通过上面三个步骤,可以依次类推,子问题又形成子问题,然后递归解决(切记,重在理解,不要死记

(2) 《数据结构教程第四版》中给出的C++代码如下:

void Hanoi(int n,char a,char b,char c)
{
	if (n==1) 
		printf("\t将第%d个盘片从%c移动到%c\n",n,a,c);
    else 
	{
		Hanoi(n-1,a,c,b);  //对应着,第一步
		printf("\t将第%d个盘片从%c移动到%c\n",n,a,c);  //对应着,第二步
		Hanoi(n-1,b,a,c);  //对应着,第三步
	}
}

(3)当初始值A中有n个圆盘的时候,要移动多少次?结合上面的代码,不难推出:

  当n = 1时: H a n o i ( n ) = 1 Hanoi(n) = 1
  当n > 1时: H a n o i ( n ) = 2 H a n o i ( n 1 ) + 1 Hanoi(n) = 2 * Hanoi(n-1) + 1

  令 f ( n ) = H a n o i ( n ) + 1 f(n) = Hanoi(n)+1 ,带入可得: f ( n ) = 2 f ( n 1 ) f(n)=2f(n-1) ,像什么?等比数列。进一步得:

   f ( n ) = 2 n f(n)=2^n ,所以得出: H a n o i ( n ) = 2 n 1 , n &gt; 0 Hanoi(n) = 2^{n} - 1, n&gt;0

Python3实现:

# @Time   :2018/10/13
# @Author :LiuYinxing
# 递归


class Solution:
    def Hanoi(self, n, a, b, c):
        if n == 1:
            print('将第%d个盘片从%c移动到%c' % (n, a, c))
        else:
            self.Hanoi(n - 1, a, c, b)  # 把 a 中最上面 n-1 个圆盘移到 b,在 a 中剩下最大的哪一个
            
            print('将第%d个盘片从%c移动到%c' % (n, a, c))  # 把 a 中最大的那个移动到 c
            
            self.Hanoi(n - 1, b, a, c)  # 现在,把 b 中上的 n-1 个圆盘,移到 c 中


if __name__ == '__main__':
    solu = Solution()
    n = 4
    a, b, c = 'A', 'B', 'C'
    solu.Hanoi(n, a, b, c)

注意: n不应过大,从推导公式可以看出,n = 64时,需要的步数普通计算机已经跑不了了,别说我的古董笔记本了。

声明: 总结学习,有问题或不妥之处,可以批评指正哦。

推导参考:www.cnblogs.com/vsky/p/5014657.html

猜你喜欢

转载自blog.csdn.net/XX_123_1_RJ/article/details/83044497
今日推荐