次のコードを検討してください。
public int heightOfBinaryTree(Node node)
{
if (node == null)
{
return 0;
}
else
{
return 1 +
Math.max(heightOfBinaryTree(node.left),
heightOfBinaryTree(node.right));
}
}
このコードの背後にある論理的な理由を知りたい。人々はどうやってそれを思いついたのですか?一部には帰納的証拠がありますか?
さらに、バイナリツリーのルートを引数としてBFSを実行して、バイナリツリーの高さを取得することを考えました。以前のアプローチは私のアプローチよりも優れていますか?
if (node == null)
{
return 0;
}
リーフノードの子はnull
です。したがって、これは葉を通過すると、それ以上のノードがないことを意味しています。
リーフノードを通過していない場合、高さを計算する必要があり、このコードは再帰的に計算します。
return 1 +
現在のノードは、現在計算されているサブツリーの高さに1の高さを追加します。
Math.max(heightOfBinaryTree(node.left),
heightOfBinaryTree(node.right));
左のサブツリー(node.left
)と右のサブツリー(node.right
)の高さを再帰的に計算します。最大深度を計算しているため、これら2つの深度の最大値を取得します。
上記で、再帰関数が正しいことを示しました。したがって、親ノードで関数を呼び出すと、ツリー全体の深さが計算されます。
このドキュメント からのツリーの高さのグラフィカルな表現を次に示します。 h
はツリーの高さ、hl
とhr
はそれぞれ左と右のサブツリーの高さです。
さらに、バイナリツリーの高さを取得するための引数としてバイナリツリーのルートを使用してBFSを実行することを考えました。以前のアプローチは私のアプローチよりも優れていますか?
指定したコードは、DFSの形式です。ツリーの高さを見つけるためにすべてのノードを処理する必要があるため、BFSはO(N)メモリを使用し、DFSはO(logN)メモリ。また、BFSは、DFSが「組み込み」再帰スタックを利用する間にキューを必要とするため、コードがやや複雑です。
そのコードの背後にあるロジックは次のとおりです。
ノードには2つの子があるため、ツリーの高さは、左の子と右の子をルートとする木の高さの最大値になり、もちろん子へのウォークでは+1になります。
ご覧のとおり、上記の説明は再帰的であり、コードも再帰的です。
BFSも実行する必要がありますが、実装と空間/時間の両方の複雑さのため、やり過ぎです。
再帰関数は理解するのは難しいが、実装するのは非常にエレガントであるという発言があります。
木の高さは、そのルートから最も長い下向きのパスの長さです。この関数は、バイナリツリーのレベルをカウントする再帰的な方法です。ツリーを下るときにカウンターをインクリメントし、最大カウンター(最下位ノードのカウンター)を返します。
お役に立てば幸いです。
これは再帰的な関数です。木の高さは、1 +その最も高い枝の高さです。
BFSは幅の広い最初の検索ですか?効率にどのような違いがあるのかはわかりませんが、再帰関数のシンプルさが気に入っています。