1. ルール
ハノイの塔は、中間の柱の助けを借りながら、スタートの柱から別のゴールの柱までプレートの積み重ねを移動させる古典的な数学の問題です。ハノイ塔のルールは以下のとおりです。
- 柱は3本あり、それぞれ「スタートの柱」「ゴールの柱」「中間の柱」と呼ばれます。
- 最初に、すべてのプレートが最大から最小の順序で開始列に積み重ねられます。
- 一度に移動できるプレートは 1 つだけであり、大きなプレートの上に小さなプレートのみを置くことができます。
- 移動中、プレートは中間コラムの助けを借りて一時的に保管できます。
- 目標は、すべてのプレートを開始列からターゲット列まで移動することです。
2. コードの実装
(1) アイデア
ルールによれば、ハノイの塔問題は再帰を使用して解決できます。再帰的解決策の手順は次のとおりです。
- プレートが 1 つしかない場合は、開始列からターゲット列に直接移動します。
- 複数のプレートがある場合は、一番下のプレートを除く上のプレートをスタート列から中央の列まで移動します (ゴール列を使用して)。
- 一番下のプレートを開始列からターゲット列に移動します。
- 以前に中央のポストに移動したプレートを、中央のポストからターゲットのポストまで移動します (開始ポストの助けを借りて)。
上記の手順を繰り返すことで、すべてのプレートを開始列から目的の列まで移動させることができ、ハノイの塔の移動が完了します。
ハノイの塔問題の解決策は指数関数的な時間計算量を伴うため、多数のプレートを扱う場合には非常に時間がかかる可能性があることに注意してください。
(2) コード
public class MyClass {
public static void main(String[] args){
// 3 是塔的层数,a 是起始柱子,b 是中间柱,c 是目标柱
tower(3, 'a', 'b', 'c');
}
//递归
public static void tower(int num, char a, char b, char c) {
//只有一个盘子时,直接将它从起始柱移动到目标柱
if (num == 1) {
System.out.println(a + " --> " + c);
} else {
//将除了最底下盘子以外的所有盘子视为一个,移动到中间柱
tower(num - 1, a, c, b);
//将最底下的盘子移动到目标柱
System.out.println(a + " --> " + c);
//将除了最底下盘子以外的所有盘子视为一个,移动到目标柱
tower(num - 1, b, a, c);
}
}
}
(3) 複雑さ
- 時間計算量:
O(2^n)
、ここで、n
はプレートの数です。 - 空間の複雑さ:
O(n)
。再帰呼び出しにより再帰スタックのオーバーヘッドが生成されるため、再帰の深さは ですn-1
。
3. 走行結果
a --> c
a --> b
c --> b
a --> c
b --> a
b --> c
a --> c