diff --git a/arai60/path-sum/README.md b/arai60/path-sum/README.md new file mode 100644 index 0000000..55db557 --- /dev/null +++ b/arai60/path-sum/README.md @@ -0,0 +1,34 @@ +## 考察 +- 過去に解いたことあり +- 方針 + - DFS/BFS + - 根から葉に向かって和を追跡していけばOK + - 条件を満たす葉を見つけた場合はその時点でreturnしたい + - BFSでやるメリットはあまりなさそう + - 再帰の深さは最大5000なので、Pythonのデフォルトだとスタックオーバーフローしてしまう +- まずは非再帰DFSで実装してみる + +## Step1 +- 非再帰DFSで実装 +- current_sumのcurrentは付けなくてもいいかもしれないが、sumが予約語なのでcurrent_sumとした +- 一応、スタック->キューにすればBFSにもなる +- time: O(n), space: O(n) + +## Step2 +- 再帰DFSでも実装 +- 他の人のPRを検索 + - https://github.com/SuperHotDogCat/coding-interview/pull/37 + - targetSumから引いていく実装をしている + - helperがいらなくなるメリットがありそう + - https://github.com/fhiyo/leetcode/pull/27 + - こちらもStep1時点でtargetSumから引いていく実装 + - 再帰で書ける場合はそちらが書きやすいことが多い + - -> そうだと思った。自分もスタックオーバーフローの危険性を説明した上で、まずは再帰で実装する動きを取ろうと思う。 + - https://github.com/sakupan102/arai60-practice/pull/26 + - 足していく実装 + - 再帰で書く時、`return find_target_path_sum(node.left, path_sum) or find_target_path_sum(node.right, path_sum)` と書いても、left childからtrueが返ってくれば、短絡評価によってright childは呼び出されないのか -> 自分のコードは冗長な書き方をしていたので修正する必要 + +## Step3 +- 1回目: 1m11s +- 2回目: 1m09s +- 3回目: 1m03s diff --git a/arai60/path-sum/step1.py b/arai60/path-sum/step1.py new file mode 100644 index 0000000..81923e0 --- /dev/null +++ b/arai60/path-sum/step1.py @@ -0,0 +1,20 @@ +# Definition for a binary tree node. +# 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 not root: return False + + nodes_to_visit = [(root, root.val)] + while nodes_to_visit: + node, current_sum = nodes_to_visit.pop() + if not node.left and not node.right and current_sum == target_sum: + return True + if node.left: + nodes_to_visit.append((node.left, current_sum + node.left.val)) + if node.right: + nodes_to_visit.append((node.right, current_sum + node.right.val)) + return False diff --git a/arai60/path-sum/step2.py b/arai60/path-sum/step2.py new file mode 100644 index 0000000..1b72f1d --- /dev/null +++ b/arai60/path-sum/step2.py @@ -0,0 +1,23 @@ +# Definition for a binary tree node. +# 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: + def has_path_sum_helper(root: TreeNode, current_sum: int) -> bool: + current_sum += root.val + if not root.left and not root.right: + return current_sum == target_sum + if root.left: + if has_path_sum_helper(root.left, current_sum): + return True + if root.right: + if has_path_sum_helper(root.right, current_sum): + return True + return False + + if not root: + return False + return has_path_sum_helper(root, 0) diff --git a/arai60/path-sum/step3.py b/arai60/path-sum/step3.py new file mode 100644 index 0000000..717f19c --- /dev/null +++ b/arai60/path-sum/step3.py @@ -0,0 +1,14 @@ +# Definition for a binary tree node. +# 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], targetSum: int) -> bool: + if not root: return False + + targetSum -= root.val + if not root.left and not root.right: + return targetSum == 0 + return self.hasPathSum(root.left, targetSum) or self.hasPathSum(root.right, targetSum)