ここでのアプローチには、他の人が対処した多くの問題があるため、代わりに、あなたが尋ねるべきでしたが、しなかった質問に答えます。
再帰を正しく使用するために問題に必要な特性は何ですか?
ソリューションが次のすべての特性を示さない限り、再帰を使用しないでください。
- 再帰なしで常に解決できる問題の「簡単な」バージョンがあります。
- すべての重要な問題は、1 つまたは複数の厳密に小さな問題に縮小できます。
- 問題をより小さな問題に繰り返し縮小すると、最終的には小さな問題を解決しようとする結果になります。つまり、「小さい」とは、たとえば、数百万ではなく数百のステップを意味する少数のステップの後です。(この条件は、「末尾再帰」言語では緩和できます。C# は末尾再帰言語ではありません。)
- 小さい問題の解決策は、より大きな問題の解決策に効率的に組み合わせることができます。
あなたのサンプル コードは、これらの特徴をまったく示していません。再帰を使用するには、これらすべての特性を示す必要があるため、いかなる状況でも再帰を使用しないでください。
再帰によってうまく解決される問題の例を挙げましょう。
ツリーは空であるか、左右のサブツリーで構成されています。ツリーにループが含まれることはありません。空の木の高さはゼロです。空でないツリーの高さは、ルートから「最も深い」空のサブツリーまでの最長パスの長さです。高さが 200 未満であると仮定して、木の高さを決定するメソッドを作成します。
この問題は、再帰で解決できる問題のすべての特徴を示しているため、再帰を実行できます。すべての再帰プログラムには次のパターンがあります。
- できれば簡単な問題を解いてください。
- それ以外の場合は、問題を小さな問題に分割し、それらを再帰的に解き、解を構成します。
それでは、それをしましょう:
int Height(Tree tree)
{
// Trivial case:
if (tree.IsEmpty) return 0;
// Non-trivial case: reduce the problem to two smaller problems:
int leftHeight = Height(tree.Left);
int rightHeight = Height(tree.Right);
int height = Math.Max(leftHeight, rightHeight) + 1;
return height;
}