-
Notifications
You must be signed in to change notification settings - Fork 0
104. Maximum Depth of Binary Tree #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
# self.val = val | ||
# self.left = left | ||
# self.right = right | ||
class Solution: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
参考までに、私はこう書きますね
class Solution:
def maxDepth(self, root: TreeNode | None) -> int:
if root is None:
return 0
left_max_depth = self.maxDepth(root.left)
right_max_depth = self.maxDepth(root.right)
return max(left_max_depth, right_max_depth) + 1
(曖昧な表現ですが)すごい人のコードを読んでいると、if文が少ないことに気づき、私も気をつけて真似するようにしています。おそらくですが、部分問題の脳内フローチャートをできるだけシンプルにしているのだと思います。
少し昔に、Linus Torvaldsさんがどこかのスピーチで、問題の捉え方を変えることで条件分岐を減らすことが言及されていました。
https://medium.com/@bartobri/applying-the-linus-tarvolds-good-taste-coding-requirement-99749f37684a
また、本を読んでいて、Cyclomatic Complexityという概念に出会いました。コードがどれくらい複雑さを表す指標で、こちらを意識すると自然と条件分岐、例えばif、の数を減らそうという働きがあるように思います。
参考まで。この私の見方が良いものなのか悪いものなのか、フィードバックを受けたことはありません。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
huyfififi さんのコードはシンプルで読みやすいですが現状のコードとの距離があると思うので、その間を埋めてみようと思います。長くなってしまいますが、ご参考になれば幸いです。
まず、left と right は対称に扱った方がわかりやすいです。
def get_max_depth(node: TreeNode, depth: int) -> int:
left_depth, right_depth = 0, 0
if node.left:
left_depth = get_max_depth(node.left, depth + 1)
if node.right:
right_depth = get_max_depth(node.right, depth + 1)
return max(depth, left_depth, right_depth)
ここから本題で、おそらくなんですが、再帰のパターンの選択が問題かなという気がしました。
get_max_depth はノードとその深さを入力にとります。子がいない場合は深さを変更せず確定させ、子がいる場合は、深さを +1 して再帰します。深さを書いた紙を部下に手渡していく感じでしょうか。過去のPRも見ていますが、garunitule さんはこのパターンがファーストチョイスになっている気がします。上から処理する方法で stack で書くと自然な考え方です。
別の再帰の仕方として、再帰する関数 (depth_of_subtree) にノードのみを入力するパターンもあります。子がいない場合はそのノードの深さは 1 になり、子がいる場合は、深い方+1 になります。部下からは報告を受けるだけです。下から処理する方法で再帰の場合こちらがわかりやすいと思います。一旦もとの root は忘れて部分木の深さを求めているとも言えます。
def maxDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
def depth_of_subtree(node: TreeNode) -> int:
left_depth, right_depth = 0, 0
if node.left is not None:
left_depth = depth_of_subtree(node.left)
if node.right is not None:
right_depth = depth_of_subtree(node.right)
return max(left_depth, right_depth) + 1
return depth_of_subtree(root)
さらに、再帰する関数で None を入力することを許容し、それは結局 maxDepth と同じだと気がつくと huyfififi さんのコードになります。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@huyfififi
シンプルで分かりやすいですね
Mediumの記事すごく面白かったです
何となくコーディング練習を通じて感じていたことに近い気がします
Arai60で色んなアルゴリズムの問題を解いていますが、結局プログラムは繰り返し・条件分岐・関数呼び出しの組み合わせでしかなく、綺麗なコードは自然に言語化できるように自然な形で概念化されているような気がしています
自然な概念化はこだわっていたのですが、シンプルさにもこだわっていくとより自然になると感じました、共有ありがとうございます!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tokuhirat
丁寧にありがとうございます
上から値を渡していく方法と、下から値を返す方法があるということですね
おっしゃる通り、再帰のときは上から渡していく方法がファーストチョイスになっていて下から値を返す方法を検討できていませんでした
選択肢として下から値を返す方法も選択肢として考えるようにします
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
今回上から渡す方法を選択すると、depthを渡す必要があってもう一つ関数が必要になるのと、root is Noneのときに0を返すかdepthを返すかの2パターンあってどうしても複雑になりますね
以下、コメントを拝見したあとに自分て実装してみたコードです
再帰、上から渡す
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
def depth_of_subtree(node: TreeNode, depth: int) -> int:
if root is None:
return depth
if node.left is not None:
depth = max(depth, self.depth_of_subtree(node.left, depth + 1))
if node.right is not None:
depth = max(depth, self.depth_of_subtree(node.right, depth + 1))
return depth
return depth_of_subtree(root, 1)
再帰、下から返す
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
left_length = self.maxDepth(root.left)
right_length = self.maxDepth(root.right)
return max(left_length, right_length) + 1
問題:104. Maximum Depth of Binary Tree
次の問題:111. Minimum Depth of Binary Tree