(來自百度百科)一位法國數學家曾編寫過一個印度的古老傳說:在世界中心貝拿勒斯(在印度北部)的聖廟裏,一塊黃銅板上插着三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片,這就是所謂的漢諾塔。不論白天黑夜,總有一個僧侶在按照下面的法則移動這些金片:一次只移動一片,不管在哪根針上,小片必須在大片上面。僧侶們預言,當所有的金片都從梵天穿好的那根針上移到另外一根針上時,世界就將在一聲霹靂中消滅,而梵塔、廟宇和衆生也都將同歸於盡。
不管這個傳說的可信度有多大,如果考慮一下把64片金片,由一根針上移到另一根針上,並且始終保持上小下大的順序。這需要多少次移動呢?這裏需要遞歸的方法。假設有n片,移動次數是f(n).顯然f⑴=1,f⑵=3,f⑶=7,且f(k+1)=2*f(k)+1。此後不難證明f(n)=2^n-1。n=64時,
f(64)= 2^64-1=18446744073709551615
假如每秒鐘一次,共需多長時間呢?一個平年365天有 31536000 秒,閏年366天有31622400秒,平均每年31556952秒,計算一下,
18446744073709551615/31556952=584554049253.855年
這表明移完這些金片需要5845億年以上,而地球存在不過45億年,太陽系的預期壽命據說也就是數百億年。真的過了5845億年,不說太陽系和銀河系,至少地球上的一切生命,連同梵塔、廟宇等,都早已經灰飛煙滅。
背景說完了,看下java實現吧。
package com.jandmin.demo.leetcode;
/**
* 漢諾塔
* 就是在一塊木板上有三個立柱,在柱1上放着三個圓盤,小的在上面,大的在下面(初始狀態)。
* 將在柱1上的三個圓盤移到柱3上面(目標狀態)。
* 條件是:每次只能移動任何一個柱子上面的一個圓盤,但大的圓盤不能放在小的圓盤上。
* @author: JandMin
* @create: 2019-06-06 09:38
**/
public class TowerOfHanoi {
public static void main(String[] args) {
// 假設3個柱子分別位 A B C,圓盤初始放在A柱上,移動C柱
char pillar1 = 'A';
char pillar2 = 'B';
char pillar3 = 'C';
// 初始圓盤數量
int count = 4;
move(count,pillar1,pillar2,pillar3);
}
/**
* @Description: 移動圓盤
* @Date: 2019/6/13
* @param count 總的圓盤數量
* @param from 第一個柱子
* @param middle 第二個柱子
* @param to 第三個柱子
* @return: void
*/
private static void move(int count, char from, char middle, char to) {
if(count < 1){
System.out.println("輸入有誤");
return;
}
if(1 == count){
print(count,from,to);
} else {
move(count-1,from,to,middle);// 2、把第n-1個盤子從 開始柱子 移到 中間柱子
print(count,from,to); // 1、把當前盤子從 開始柱子 移到 目標柱子
move(count-1,middle,from,to);// 3、把第n-1個盤子從 中間柱子 移到 目標柱子
}
}
/**
* @Description: 打印移動過程
* @Date: 2019/6/13
* @param num 第幾個圓盤
* @param from
* @param to
* @return: void
*/
private static void print(int num, char from, char to) {
System.out.println("第 " + num + " 個圓盤: " + from + " ---> " + to);
}
}