From e7dcbdf61b2983f33aa079e32db7562b1ca5f99c Mon Sep 17 00:00:00 2001 From: Yota Maeda Date: Fri, 10 Jul 2026 21:40:31 +0900 Subject: [PATCH 1/3] step1 --- 112-Path-Sum/note.md | 16 ++++++++++++++++ 112-Path-Sum/step1-2y.py | 22 ++++++++++++++++++++++ 112-Path-Sum/step1.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 112-Path-Sum/note.md create mode 100644 112-Path-Sum/step1-2y.py create mode 100644 112-Path-Sum/step1.py diff --git a/112-Path-Sum/note.md b/112-Path-Sum/note.md new file mode 100644 index 0000000..e3ef4bb --- /dev/null +++ b/112-Path-Sum/note.md @@ -0,0 +1,16 @@ +# 112. Path Sum + +https://leetcode.com/problems/path-sum/ + +## step1(まず通す) + +ノードを全部探索して、条件に該当するものが見つかったら return true すればいい。 + +ループで書くなら (node, sum_so_far) みたいに持ちたい。その場合は深さ優先探索でも幅優先探索でもいいが、該当するパスが見つかった時点で return できるので深さ優先探索の方が見るノード数が少なくて済むことが多そう。 +他の方のコードでよく見かける `forntiers` という変数名を使ってみた。 + +再帰でも書ける(step1-2.py)。一本道だと再帰呼び出しの回数がノード数(最大 5000)になるので、注意が必要(Python の再帰呼び出し回数の上限はデフォルトだと 1000) + +## step2(整形&他の人のコードを読む) + +## step3(10分以内にさっとかける \* 3回) diff --git a/112-Path-Sum/step1-2y.py b/112-Path-Sum/step1-2y.py new file mode 100644 index 0000000..fb2ecd3 --- /dev/null +++ b/112-Path-Sum/step1-2y.py @@ -0,0 +1,22 @@ +from typing import Optional + + +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution: + def hasPathSum(self, root: Optional[TreeNode], target_sum: int) -> bool: + if root is None: + return False + + if root.left is None and root.right is None and root.val == target_sum: + return True + + children_target_sum = target_sum - root.val + return self.hasPathSum(root.left, children_target_sum) or self.hasPathSum( + root.right, children_target_sum + ) diff --git a/112-Path-Sum/step1.py b/112-Path-Sum/step1.py new file mode 100644 index 0000000..e953c5e --- /dev/null +++ b/112-Path-Sum/step1.py @@ -0,0 +1,28 @@ +from typing import Optional + + +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution: + def hasPathSum(self, root: Optional[TreeNode], target_sum: int) -> bool: + if root is None: + return False + + frontiers = [(root, 0)] + while frontiers: + node, sum_so_far = frontiers.pop() + sum_so_far += node.val + if node.left is None and node.right is None and sum_so_far == target_sum: + return True + + if node.left is not None: + frontiers.append((node.left, sum_so_far)) + if node.right is not None: + frontiers.append((node.right, sum_so_far)) + + return False From 370c13510d7d557cc889b822b9b5097926a15b22 Mon Sep 17 00:00:00 2001 From: Yota Maeda Date: Fri, 10 Jul 2026 21:56:56 +0900 Subject: [PATCH 2/3] step2 --- 112-Path-Sum/note.md | 22 ++++++++++++++++++++++ 112-Path-Sum/step2.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 112-Path-Sum/step2.py diff --git a/112-Path-Sum/note.md b/112-Path-Sum/note.md index e3ef4bb..b80d3b6 100644 --- a/112-Path-Sum/note.md +++ b/112-Path-Sum/note.md @@ -13,4 +13,26 @@ https://leetcode.com/problems/path-sum/ ## step2(整形&他の人のコードを読む) +- https://github.com/naoto-iwase/leetcode/pull/29#discussion_r2455081026 + - 「もし葉でtargetSumになるような経路を返却するとしたらどうでしょうか?設問としてはTrue/Falseなのですが、単純にTrue/Falseを得るよりはpathを実際に知るほうが意味があるのかなと思ったので...自分が面接だったら質問しそうです。」 + - 葉から根へ向かうのは親を辿っていけば一本道でたどり着くので、探索しながら各ノードの親を覚えておく `node_to_parent: dict[TreeNode, TreeNode` 辞書を作って、葉から順番に辿っていけば良さそう。 +- https://discord.com/channels/1084280443945353267/1225849404037009609/1258455843226255361 + - 「引き算先にしちゃって、...のほうが素直ではないでしょうか。」 + - 確かにそう。 + +```python +class Solution: + def hasPathSum(self, root: Optional[TreeNode], target_sum: int) -> bool: + if root is None: + return False + + children_target_sum = target_sum - root.val + if root.left is None and root.right is None: + return children_target_sum == 0 + + return self.hasPathSum(root.left, children_target_sum) or self.hasPathSum( + root.right, children_target_sum + ) +``` + ## step3(10分以内にさっとかける \* 3回) diff --git a/112-Path-Sum/step2.py b/112-Path-Sum/step2.py new file mode 100644 index 0000000..4d95c0a --- /dev/null +++ b/112-Path-Sum/step2.py @@ -0,0 +1,31 @@ +from typing import Optional + + +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution: + def hasPathSum(self, root: Optional[TreeNode], target_sum: int) -> bool: + if root is None: + return False + + frontiers = [(root, target_sum)] + while frontiers: + node, rest = frontiers.pop() + rest -= node.val + if node.left is None and node.right is None: + if rest == 0: + return True + else: + continue + + if node.left is not None: + frontiers.append((node.left, rest)) + if node.right is not None: + frontiers.append((node.right, rest)) + + return False From a6262675e674e18e5f5277024cfc7ae307e7ca73 Mon Sep 17 00:00:00 2001 From: Yota Maeda Date: Tue, 14 Jul 2026 21:03:58 +0900 Subject: [PATCH 3/3] step3 --- 112-Path-Sum/note.md | 31 +++++++++++++++++++++++++++++++ 112-Path-Sum/step3.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 112-Path-Sum/step3.py diff --git a/112-Path-Sum/note.md b/112-Path-Sum/note.md index b80d3b6..ed19c78 100644 --- a/112-Path-Sum/note.md +++ b/112-Path-Sum/note.md @@ -16,6 +16,37 @@ https://leetcode.com/problems/path-sum/ - https://github.com/naoto-iwase/leetcode/pull/29#discussion_r2455081026 - 「もし葉でtargetSumになるような経路を返却するとしたらどうでしょうか?設問としてはTrue/Falseなのですが、単純にTrue/Falseを得るよりはpathを実際に知るほうが意味があるのかなと思ったので...自分が面接だったら質問しそうです。」 - 葉から根へ向かうのは親を辿っていけば一本道でたどり着くので、探索しながら各ノードの親を覚えておく `node_to_parent: dict[TreeNode, TreeNode` 辞書を作って、葉から順番に辿っていけば良さそう。 + - 全部のパスを返す必要があるなら、見つかった時点での return をやめて全ノードを探索すれば良い。 + - パスを一つだけ見つければ良いという条件で再帰で書くなら↓のようになるだろうか。空リストより None が良いかもしれないのと、パスを探すならパスの存在自体が T/F の代わりになるので bool を返す必要はなさそう。全部のパスを返す場合は、返すのがパスのリスト = ノードのリストのリストになってだいぶ煩雑な気がする。 + +```python +class Solution: + def hasPathSum( + self, root: Optional[TreeNode], target_sum: int + ) -> tuple[bool, list[TreeNode]]: + if root is None: + return False, [] + + if root.left is None and root.right is None: + if root.val == target_sum: + return True, [root] + else: + return False, [] + + child_target_sum = target_sum - root.val + left_has_path, path = self.hasPathSum(root.left, child_target_sum) + if left_has_path: + path.append(root) + return True, path + + right_has_path, path = self.hasPathSum(root.right, child_target_sum) + if right_has_path: + path.append(root) + return True, path + + return False, [] +``` + - https://discord.com/channels/1084280443945353267/1225849404037009609/1258455843226255361 - 「引き算先にしちゃって、...のほうが素直ではないでしょうか。」 - 確かにそう。 diff --git a/112-Path-Sum/step3.py b/112-Path-Sum/step3.py new file mode 100644 index 0000000..4d95c0a --- /dev/null +++ b/112-Path-Sum/step3.py @@ -0,0 +1,31 @@ +from typing import Optional + + +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution: + def hasPathSum(self, root: Optional[TreeNode], target_sum: int) -> bool: + if root is None: + return False + + frontiers = [(root, target_sum)] + while frontiers: + node, rest = frontiers.pop() + rest -= node.val + if node.left is None and node.right is None: + if rest == 0: + return True + else: + continue + + if node.left is not None: + frontiers.append((node.left, rest)) + if node.right is not None: + frontiers.append((node.right, rest)) + + return False