-
Notifications
You must be signed in to change notification settings - Fork 0
104, Maximum Depth of Binary Tree #14
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,170 @@ | ||||||
## Step1 | ||||||
|
||||||
- 最初に思いついた解法 | ||||||
- depthを中でも参照するために、returnでdepth, max_depthの両方を返してしまったが、そもそもclassなのでself.で再帰関数を定義すればよかった | ||||||
- 最初はreturn depth_search(depth, root, max_depth)[1]だったが見にくい気がして直す | ||||||
- なぜか実行速度も45ms→33msに | ||||||
|
||||||
```python | ||||||
|
||||||
class Solution: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. だいぶ読みにくいです。表層的にはdepth, max_depthを取り回している部分をやめるとある程度改善されそうな気がしています。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. このコードは一発で書けましたか?何回かfailしましたか?自分はこのコードを1回で書ける自信がないです。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. これは、 「depth, max_depthの値を保存するぞ」という意志のもと2で直したので、その変数をたくさん使ってしまい、上書き処理が多くなってしまいました。 自分の中ではdepthがそれぞれの関数のなかでそれぞれの深さを表しているつもりで、そんなに詰まらず書いてしまったのですが、上書き処理が多くなったせいで読む側にとってはわかりにくくなってしまったのかもしれません。あと、関数の処理の最初ではなく引数の時点で足すという選択肢がなかったです。大変参考になります。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ちなみに、同じ変数名で値が頻繁に変わるコードは一般に読みにくいと思われるのでしょうか。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 値が変わること自体はそこまで問題でなくて変数の意味が変わるので読みにくいのかなと思いました。 同じdepthという変数名でもそれぞれ以下の意味あいがあるはずで、読む側としてはいまのdepthが表しているものを文脈に応じて考える必要があって結構大変です。 L12:1つ上のノードの深さ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nittocoさんのアルゴリズムを別のやり方で実装するとこんな感じになりますかね。 class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
depth = 0
max_depth = 0
def find_max_depth(node):
nonlocal depth, max_depth
if not node:
return
depth += 1
max_depth = max(depth, max_depth)
find_max_depth(node.left)
find_max_depth(node.right)
depth -= 1
find_max_depth(root)
return max_depth There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. そもそも There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 確かに最初と最後で+1, -1をする方が綺麗ですね There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nonlocalが非推奨ってどこに書いてますか? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. おお、nonlocalとglobalって違うんですね、今気づきました。ありがとうございます |
||||||
def maxDepth(self, root: Optional[TreeNode]) -> int: | ||||||
def depth_search(depth, current_node, max_depth): | ||||||
depth += 1 | ||||||
if not current_node: | ||||||
return depth, max_depth | ||||||
max_depth = max(depth, max_depth) | ||||||
depth, max_depth = depth_search(depth, current_node.left, max_depth) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
この2つである程度改善されないですかね?
|
||||||
depth -= 1 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. このdepthを1減らしている処理だけでも理解するのが結構しんどかったです。 引数のdepthは1つ上のノードの深さで、再帰関数の先頭で+1しているのでその時点で現在のノードの深さになっているが、直前のdepth_searchの呼び出しで1つ下のノードの深さが帰ってきているので現在のノードの深さに戻すために1を引く、処理を全部追ってここまでしないと-1をしている理由が分からないです。 |
||||||
depth, max_depth = depth_search(depth, current_node.right, max_depth) | ||||||
depth -= 1 | ||||||
return depth, max_depth | ||||||
|
||||||
depth = 0 | ||||||
max_depth = 0 | ||||||
depth, max_depth = depth_search(depth, root, max_depth) | ||||||
return max_depth | ||||||
``` | ||||||
|
||||||
## Step2 | ||||||
|
||||||
- [ahayashiさん](https://github.com/hayashi-ay/leetcode/pull/22/files)のをみた。よく考えたら、再帰ならdepthは持たなくても良い | ||||||
|
||||||
```python | ||||||
class Solution: | ||||||
def maxDepth(self, root: Optional[TreeNode]) -> int: | ||||||
if not root: | ||||||
return 0 | ||||||
max_depth = max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1 | ||||||
return max_depth | ||||||
``` | ||||||
|
||||||
- 上のは簡潔だけど、left_depthとright_depthで一旦分けといた方がいいのか?迷う | ||||||
- Step3では分けることに | ||||||
- BFS順に見ていくやつも実装してみた | ||||||
- 1回目(失敗作)が上、直したのが下 | ||||||
|
||||||
```python | ||||||
python | ||||||
class Solution: | ||||||
def maxDepth(self, root: Optional[TreeNode]) -> int: | ||||||
if not root: | ||||||
return 0 | ||||||
depth = 1 | ||||||
current_node = [root] | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. listなので There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 下では複数形にしてますね。 |
||||||
while current_node: | ||||||
depth += 1 | ||||||
next_node = [] | ||||||
if current_node.left: | ||||||
next_node.append(current_node.left) | ||||||
if current_node.right: | ||||||
next_node.append(curent_node.right) | ||||||
current_node = next_node | ||||||
return depth | ||||||
``` | ||||||
|
||||||
|
||||||
```python | ||||||
|
||||||
class Solution: | ||||||
def maxDepth(self, root: Optional[TreeNode]) -> int: | ||||||
if not root: | ||||||
return 0 | ||||||
current_nodes = [root] | ||||||
depth = 0 | ||||||
while current_nodes: | ||||||
depth += 1 | ||||||
next_nodes = [] | ||||||
for node in current_nodes: | ||||||
if node.left: | ||||||
next_nodes.append(node.left) | ||||||
if node.right: | ||||||
next_nodes.append(node.right) | ||||||
current_nodes = next_nodes | ||||||
return depth | ||||||
``` | ||||||
|
||||||
- DFS順のやつも実装、StackでDFSを実装するのは初めてなので練習 | ||||||
- 割とすぐできた、うっかりappend(node.right, depth+1)とやってしまい一瞬あれ、となってたけど | ||||||
- [これ](https://github.com/shining-ai/leetcode/pull/21/files)を見る限り、node_depthという変数名よりstack_node_depthとstackであることを明示した方がいいのかな | ||||||
- 迷う | ||||||
|
||||||
```python | ||||||
class Solution: | ||||||
def maxDepth(self, root: Optional[TreeNode]) -> int: | ||||||
if not root: | ||||||
return 0 | ||||||
depth = 1 | ||||||
max_depth = 1 | ||||||
node_depth = [(root, depth)] | ||||||
while node_depth: | ||||||
node, depth = node_depth.pop() | ||||||
max_depth = max(max_depth, depth) | ||||||
if node.right: | ||||||
node_depth.append((node.right, depth+1)) | ||||||
max_depth = max(max_depth, depth) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ifの前でmax_depthを求めているので不要な気がします。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 下では消してますね。 |
||||||
if node.left: | ||||||
node_depth.append((node.left, depth+1)) | ||||||
max_depth = max(max_depth, depth) | ||||||
return max_depth | ||||||
``` | ||||||
|
||||||
## Step3 | ||||||
|
||||||
- BFS(これが一番詰まる) | ||||||
|
||||||
```python | ||||||
def maxDepth(self, root: Optional[TreeNode]) -> int: | ||||||
if not root: | ||||||
return 0 | ||||||
depth = 0 | ||||||
current_nodes = [root] | ||||||
while current_nodes: | ||||||
depth += 1 | ||||||
next_nodes = [] | ||||||
for node in current_nodes: | ||||||
if node.left: | ||||||
next_nodes.append(node.left) | ||||||
if node.right: | ||||||
next_nodes.append(node.right) | ||||||
current_nodes = next_nodes | ||||||
return depth | ||||||
``` | ||||||
|
||||||
- DFS | ||||||
|
||||||
よく考えたら、maxを取るのはpop()する時だけでOK | ||||||
|
||||||
```python | ||||||
|
||||||
class Solution: | ||||||
def maxDepth(self, root: Optional[TreeNode]) -> int: | ||||||
if not root: | ||||||
return 0 | ||||||
node = root | ||||||
depth = 1 | ||||||
stack_node_depth = [(node, depth)] | ||||||
max_depth = 1 | ||||||
while stack_node_depth: | ||||||
node, depth = stack_node_depth.pop() | ||||||
max_depth = max(max_depth, depth) | ||||||
if node.right: | ||||||
stack_node_depth.append((node.right, depth+1)) | ||||||
if node.left: | ||||||
stack_node_depth.append((node.left, depth+1)) | ||||||
return max_depth | ||||||
``` | ||||||
|
||||||
- 再帰(これは簡単) | ||||||
- なぜかmax_depth = max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1と一気に書くよりだいぶ遅い(一気に書くのは27ms、下のは40ms) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 測定の誤差に含まれる気がします。 |
||||||
|
||||||
```python | ||||||
|
||||||
class Solution: | ||||||
def maxDepth(self, root: Optional[TreeNode]) -> int: | ||||||
if not root: | ||||||
return 0 | ||||||
left_depth = self.maxDepth(root.left) | ||||||
right_depth = self.maxDepth(root.right) | ||||||
return max(left_depth, right_depth) + 1 | ||||||
``` |
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.
Pythonの実行速度は実行ごとに結構変わるので何回か実行して比較してみると良いと思います。
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.
本当ですね、33msだったのが今度は47msになったりします。
これくらいだと測定誤差ですね。ありがとうございます。