百度測試部2015年10月份的面試題之——漢諾塔。
漢諾塔就是將一摞盤子從一個塔轉移到另一個塔的遊戲,中間有一個用來過度盤子的輔助塔。
百度百科在此。
遊戲試玩在此。
用遞迴的思想解決漢諾塔問題就是分為兩種情況:
第一種情況是隻有一個盤子的情況,也就是最基本的情況,這種情況下,直接將該盤子從原始塔轉移到目標塔即可勝利;
第二種情況是右n個盤子的情況,也就是普遍情況,這種情況下,要將除了最底下的那個盤子以外的(n-1)個盤子從原始塔轉移到輔助塔,再把最底下的那個盤子(第n個盤子)從原始塔轉移到目標塔,最後將輔助塔的(n-1)個盤子從輔助塔轉移到目標塔。
而第二種情況中(n-1)個盤子的問題又可以拆分成(n-2)個盤子和一個盤子的問題——
而(n-2)個盤子的問題又可以拆分成(n-3個情況)和一個盤子的問題——
……
最終可以拆分成(n-(n-1))個盤子的問題,也就是一個盤子的問題,這時候問題就變成了第一種情況——
將這個盤子從原始塔轉移到目標塔即可。
以上就是遞迴的思想在解漢諾塔遊戲中的應用,我們可以理解這種遞迴法為類似數學歸納法的逆向思維法:
數學歸納法是一種從問題最基本情況的求解過程通過找規律從而得出該問題普遍情況的求解過程的方法;
遞迴法是將對問題普遍情況的求解過程進行拆分,最後分解為對一種最基本情況的求解過程的方法。
通過遞迴法解決漢諾塔的移動順序問題程式碼如下:
using System; namespace HanoiTower { class Program { static void Main(string[] args) { int n = Int32.Parse(Console.ReadLine()); Hanoi(n,"TowerA","TowerB","TowerC"); Console.ReadLine(); } private static void Hanoi(int n, string origin, string temp, string destination) { if (n == 1) { move(origin, destination); } else { Hanoi(n - 1, origin, destination, temp); move(origin, destination); Hanoi(n - 1, temp, origin, destination); } } private static void move(string origin, string destination) { Console.WriteLine("Move the plate from " + origin + " to " + destination); } } }
執行結果如下(以三個盤子的情況為例,大家可以去遊戲中操作來驗證解的正確性):