遞迴是演算法課中最重要的一門必修課,也是我們繞不開的坎,寫這篇文章的目的主要是以練代學,一步一步理解遞迴,形成肌肉記憶
有很多理論性的文章,教你如何理解遞迴,看完之後還是很懵逼,最初我學遞迴的時候直接是從入門到放棄,然後打算直接刷題,在題量的累積下,頓悟了
概念上的東西不解釋太多,簡單說一下就是,有三根柱子 a (左),b() , c 。現在要把 a 柱上的盤子全部移到 b 柱上,移動過程中必須遵守乙個原則:只有小盤子才能壓在**子上
因為一次我們只能移動乙個盤子,所以需要移動 7 次才可解決問題,即:
把 小盤 從 左 移到 右
把 中盤 從 左 移動 中
把 小盤 從 右 移到 左
最大的盤子 從 左 移到 右
把 小盤 從 **中 -> 左 **
中盤 從中 -> 右
最後一步 :小盤 從左 -> 右
過程很簡單,因為一次只能移動最頂上的盤子,所以我們要移動**子,就要把它上面的小盤子全部移走才行
我們來看一下coding
public static void hanoi(int n)
private static void lefttoright(int n)
// 把 n-1 層盤子從左移到中,
// 再把最底下的盤子移到右,再把中間的 n-1 層盤子移到右
lefttomid(n - 1);
system.out.println("move " + n + " from left to right");
midtoright(n - 1);
}
是不是很簡單
我們再看一下 lefttomid 方法怎麼寫
還是和之前一樣分析, 我們要把 n 層盤子從左移到中,就需要先把 n-1 個盤子從左挪到右,然後把左邊最底下的盤子挪到中,然後再把 n-1 層盤子從右邊挪到中間
private static void lefttomid(int n)
// 要把 n 層盤子從左挪到中,需要先把 n-1 層挪出去給第 n 層騰位置
// 所以把 n-1 層從左挪到右
lefttoright(n - 1);
// 再把第 n 層挪到中
system.out.println("move " + n + " from left to mid");
// 再把挪到右邊的 n-1 層挪回來
righttomid(n - 1);
}
完整**如下:
public static void hanoi(int n)
/** * 把 n 層圓盤,從左 -> 右
* @param n
*/private static void lefttoright(int n)
// 把 n-1 層盤子從左移到中,
// 再把最底下的盤子移到右,再把中間的 n-1 層盤子移到右
lefttomid(n - 1);
system.out.println("move " + n + " from left to right");
midtoright(n - 1);
}private static void lefttomid(int n)
// 要把 n 層盤子從左挪到中,需要先把 n-1 層挪出去給第 n 層騰位置
// 所以把 n-1 層從左挪到右
lefttoright(n - 1);
// 再把第 n 層挪到中
system.out.println("move " + n + " from left to mid");
// 再把挪到右邊的 n-1 層挪回來
righttomid(n - 1);
}private static void righttomid(int n)
righttoleft(n - 1);
system.out.println("move " + n + " from right to mid");
lefttomid(n - 1);
}private static void righttoleft(int n)
righttomid(n - 1);
system.out.println("move " + n + " from right to left");
midtoleft(n - 1);
}private static void midtoleft(int n)
midtoright(n - 1);
system.out.println("move " + n + " from mid to left");
righttoleft(n - 1);
}private static void midtoright(int n)
midtoleft(n - 1);
system.out.println("move " + n + " from mid to right");
lefttoright(n - 1);
}
這就是傻白甜的漢諾塔問題
這個過程我們可以優化一下,我們先忘掉左中右,假如我們現在還是有三個柱子:from,to,other
我們需要把 n 層盤子從 from 挪到 to 去,首先我們要把 n-1 層盤子挪到 other 上,然後把 n 從 from 挪到 to, 再把 other 上的 n-1 層盤子挪到 to,other 作為騰位置的柱子。
優化後的**:
public static void hanoi2(int n)
} public static void func(int n, string from, string to, string other)
// 把 n-1 層從 from 挪到 other 上,to 充當騰位置的柱子
func(n - 1, from, other, to);
system.out.println("move " + n + " from " + from + " to " + to);
// 把 n-1 層從 other 挪到 to ,from 充當騰位置的柱子
func(n - 1, other, to, from);
}
這是我寫遞迴入門的第一篇文章,後面會繼續**包括 記憶化遞迴,遞迴到動態規劃等
我最開始學遞迴的時候,也覺得遞迴是一門玄學,不過這都不重要
重要的是我們需要有黑盒思維,什麼是黑盒思維?
就是我們不用關注這個 api 是怎麼實現的,我們只需要知道他能返回給我們需要的結果即可
C語言 遞迴入門 漢諾塔問題
在定義乙個過程或函式時,出現呼叫本過程或本函式的成分稱為遞迴 如果乙個遞迴過程或函式中的遞迴呼叫語句是最後一條執行語句,則稱這種遞迴呼叫為尾遞迴 例如 計算階乘函式 intf int n else return f n 1 n 遞迴解決問題應滿足三個條件 需要解決的問題可以轉化為乙個或多個子問題求解...
漢諾塔問題(遞迴)
題目描述 對於傳統的漢諾塔遊戲我們做乙個拓展,我們有從大到小放置的n個圓盤,開始時所有圓盤都放在左邊的柱子上,按照漢諾塔遊戲的要求我們要把所有的圓盤都移到右邊的柱子上,請實現乙個函式列印最優移動軌跡。給定乙個int n,表示有n個圓盤。請返回乙個string陣列,其中的元素依次為每次移動的描述。描述...
漢諾塔問題(遞迴)
問題 漢諾塔問題 解法 遞迴求解 思路 先把n 1從a移動b 在把第n個從a移到c 使用遞迴使得 變得簡單 複雜度 2的n次方 1 includeint step 1 void hanoi int level,char a,char b,char c 1 當盤子數大於1時,先把n 1個從a借助c移動...