diff --git a/112. Path Sum.md b/112. Path Sum.md new file mode 100644 index 0000000..8bdc15a --- /dev/null +++ b/112. Path Sum.md @@ -0,0 +1,139 @@ +### Step1 + +- 本当は部下に仕事を任せてreturnしてもらう実装が好きだが、値の候補がたくさんreturnされてしまうのがどうかと思い、backtrackingで書いた +- nonlocalでもいいが、mutableなリストで書いた +- 最初、子供がいるかは判定せずに、if not node: の時にtargetと照合しようとして失敗。片方しか子供がいない時にも判定されてしまう。 +- このbacktrackingのアルゴリズムをリファクタリンぎしたやつをStep2の最後に記載 + +```python + +class Solution: + def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool: + def search_target_sum(sum_so_far, node: Optional[TreeNode]): + sum_so_far += node.val + if not (node.left or node.right): + if sum_so_far == targetSum: + has_target[0] = True + if node.left: + search_target_sum(sum_so_far, node.left) + if node.right: + search_target_sum(sum_so_far, node.right) + sum_so_far -= node.val + + if not root: + return False + has_target = [False] + search_target_sum(0, root) + return has_target[0] +``` + +### Step2 +- [参考] + - (https://github.com/TORUS0818/leetcode/pull/27/files) + - (https://github.com/kazukiii/leetcode/pull/26/files) +- 再帰をするなら、単にFalse, Trueを返す関数を作ればよかった。(なぜか変にsumを全部返さなきゃとか思ってしまった) +- 下でこれをさらにリファクタしてます + +```python + +class Solution: + def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool: + def search_target_sum(sum_so_far, node: Optional[TreeNode]): + sum_so_far += node.val + if not (node.left or node.right): + return sum_so_far == targetSum + if node.left and search_target_sum(sum_so_far, node.left): + return True + if node.right and search_target_sum(sum_so_far, node.right): + return True + return False + + if not root: + return False + return search_target_sum(0, root) +``` + +- if not node: でreturn Falseすればいいのか〜 + - なんか、葉であるのとnodeがそもそもないのを両方関数内で判定すると言う発想がなかった + - こう言うのは最後のないところまで探索するのがいいね + +```python + +class Solution: + def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool: + def search_target_sum(sum_so_far, node: Optional[TreeNode]): + if not node: + return False + sum_so_far += node.val + if not (node.left or node.right): + return sum_so_far == targetSum + return search_target_sum(sum_so_far, node.left) or search_target_sum(sum_so_far, node.right) + + return search_target_sum(0, root) +``` + +- 手でやるならbacktrackingのように足し引きしながら計算する気がするので、Step1を綺麗にしたやつを書いてみる + - [True]みたいに要素数1のリストを持たせるのも微妙かと思い、path_sumsをsetで持たせることにした + - returnに()をつけるか迷った(つけないと分かりにくいか、不要か) + +```python + +class Solution: + def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool: + def caluculate_path_sums(sum_so_far, node: Optional[TreeNode], path_sums: set): + if not node: + return + sum_so_far += node.val + if not node.left and not node.right: + path_sums.add(sum_so_far) + caluculate_path_sums(sum_so_far, node.left, path_sums) + caluculate_path_sums(sum_so_far, node.right, path_sums) + sum_so_far -= node.val + + path_sums = set() + caluculate_path_sums(0, root, path_sums) + return (targetSum in path_sums) +``` + +## Step3(レビュー反映復習) +```python + +class Solution: + def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool: + def search_target_sum(sum_so_far, node: Optional[TreeNode]): + nonlocal has_target + if not node: + return + sum_so_far += node.val + if not node.left and not node.right: + if sum_so_far == targetSum: + has_target = True + return + search_target_sum(sum_so_far, node.left) + search_target_sum(sum_so_far, node.right) + + has_target = False + search_target_sum(0, root) + return has_target +``` + +- こうは書かないけど一応 + +```python +python +class Solution: + def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool: + def calculate_path_sums(node, sum_so_far): + if not node: + return + sum_so_far += node.val + if not node.left and not node.right: + path_sums.add(sum_so_far) + calculate_path_sums(node.left, sum_so_far) + calculate_path_sums(node.right, sum_so_far) + + path_sums = set() + calculate_path_sums(root, 0) + return targetSum in path_sums + +```