Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions arai60/path-sum/README.md
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions arai60/path-sum/step1.py
Original file line number Diff line number Diff line change
@@ -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
23 changes: 23 additions & 0 deletions arai60/path-sum/step2.py
Original file line number Diff line number Diff line change
@@ -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:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この直後に、

if not root:
    return False

としておくと、下の条件が少し減らせます。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コメントありがとうございます。3つ分岐を減らせました。

class Solution:
    def hasPathSum(self, root: Optional[TreeNode], target_sum: int) -> bool:
        def has_path_sum_helper(root: TreeNode, current_sum: int) -> bool:
            if not root:
                return False
            current_sum += root.val
            if not root.left and not root.right:
                return current_sum == target_sum
            if has_path_sum_helper(root.left, current_sum):
                    return True
            if has_path_sum_helper(root.right, current_sum):
                    return True
            return False

        return has_path_sum_helper(root, 0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

さらに

return has_path_sum_helper(root.left, current_sum) or has_path_sum_helper(root.right, current_sum)

ともできますね。

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):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if root.left and has_path_sum_helper(root.left, current_sum):で書けそうです。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

たしかにこちらの方がネストが浅くなっていいと思いました。

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)
14 changes: 14 additions & 0 deletions arai60/path-sum/step3.py
Original file line number Diff line number Diff line change
@@ -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)
Comment on lines +11 to +14

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好みかも。自分はあまり値を動かしたくないので以下みたいに書く気がします。

if not root.left and not root.right:
  return targetSum == root.val
return self.hasPathSum(root.left, targetSum - rootl.val) or self.hasPathSum(root.right, targetSum - root.val)