-
Notifications
You must be signed in to change notification settings - Fork 0
112. Path Sum #31
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?
112. Path Sum #31
Conversation
https://leetcode.com/problems/path-sum/description/ Given the root of a binary tree and an integer targetSum, return true if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum. A leaf is a node with no children.
| search_target_sum(sum_so_far, node.left) | ||
| if node.right: | ||
| search_target_sum(sum_so_far, node.right) | ||
| sum_so_far -= node.val |
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.
sum_so_far -= node.valこれ必要でしょうか。
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.
不要でしょう。
| 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 |
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.
sum_so_far -= node.valこれ必要でしょうか。
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.
手作業でbacktrackingするなら戻る時に引くなあと思って入れたんですが、よく考えたら引いた後に関数内でなんか操作している訳ではないのでいらなかったですね。
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.
sum_so_farをcall stackに積まないで、nonlocalとして扱う書き方もありますね。その場合は、一歩戻るときに sum_so_far -= node.val を入れてあげないとですね。
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.
確かに、自分が頭でシミュレーションしてたのをコードに書くならそれになりますね。
スッキリしました、ありがとうございます。
| ``` | ||
|
|
||
| - 手でやるならbacktrackingのように足し引きしながら計算する気がするので、Step1を綺麗にしたやつを書いてみる | ||
| - [True]みたいに要素数1のリストを持たせるのも微妙かと思い、path_sumsをsetで持たせることにした |
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.
全ての根から葉までの和を保持しておくのはやや贅沢な気がします。
少し設定を変えてtargetSumに合致するようなパスがいくつあるか数える時、とかならこういう実装も良さそうですね。
|
|
||
| - 手でやるならbacktrackingのように足し引きしながら計算する気がするので、Step1を綺麗にしたやつを書いてみる | ||
| - [True]みたいに要素数1のリストを持たせるのも微妙かと思い、path_sumsをsetで持たせることにした | ||
| - returnに()をつけるか迷った(つけないと分かりにくいか、不要か) |
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.
個人的には不要かなと思いました。分かりやすくなっていない気がするので。
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.
不要でしょう。
| 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) |
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.
ここにtargetSumを渡して、関数内で引いていく方式にすればスコープ外の変数を使わなくて済むのでそれも手だと思います
付随した質問: よくPythonコードでスコープ外の変数を使っている人を見かけるのですが、これって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.
「スコープ外の変数を使う」とは今回の場合、69行目において、targetSumが外側にある、ということですよね。それをしたくない理由は、挙動が追いにくいからでしょうか。(言われれば確かにそう感じる理由もわかる気がします)
自分は大規模コードの開発経験がないのでいまいち一般的な感覚がわからないのですが、どうなんでしょう…?
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.
特に問題ないと思います。
| ### Step1 | ||
|
|
||
| - 本当は部下に仕事を任せてreturnしてもらう実装が好きだが、値の候補がたくさんreturnされてしまうのがどうかと思い、backtrackingで書いた | ||
| - nonlocalでもいいが、mutableなリストで書いた |
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.
nonlocalの方が意図が明確だと思います。
| search_target_sum(sum_so_far, node.left) | ||
| if node.right: | ||
| search_target_sum(sum_so_far, node.right) | ||
| sum_so_far -= node.val |
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.
不要でしょう。
| 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): |
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.
not node.left and not node.rightの方がわかりやすく感じます。
| sum_so_far += node.val | ||
| if not (node.left or node.right): | ||
| if sum_so_far == targetSum: | ||
| has_target[0] = True |
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.
ここでreturnしたら良いでしょう。
| @@ -0,0 +1,96 @@ | |||
| ### Step1 | |||
|
|
|||
| - 本当は部下に仕事を任せてreturnしてもらう実装が好きだが、値の候補がたくさんreturnされてしまうのがどうかと思い、backtrackingで書いた | |||
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.
答えを一つ見つけたら、そこで打ち切った方が良いでしょう。
| - [参考] | ||
| - (https://github.com/TORUS0818/leetcode/pull/27/files) | ||
| - (https://github.com/kazukiii/leetcode/pull/26/files) | ||
| - 再帰をするなら、単にFalse, Trueを返す関数を作ればよかった。(なぜか変にsumを全部返さなきゃとか思ってしまった) |
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.
Step 1でも、sumは返していないようです。
| return True | ||
| return False | ||
|
|
||
| if not root: |
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.
search_target_sumの中に入れたほうが、コードの重複が減りますね。
| 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) |
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.
特に問題ないと思います。
|
|
||
| - 手でやるならbacktrackingのように足し引きしながら計算する気がするので、Step1を綺麗にしたやつを書いてみる | ||
| - [True]みたいに要素数1のリストを持たせるのも微妙かと思い、path_sumsをsetで持たせることにした | ||
| - returnに()をつけるか迷った(つけないと分かりにくいか、不要か) |
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.
不要でしょう。
|
|
||
| class Solution: | ||
| def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool: | ||
| def caluculate_path_sums(sum_so_far, node: Optional[TreeNode], path_sums: set): |
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.
path_sumsを引数として渡す必要はなさそうです。
| ## Step3(レビュー反映復習) | ||
| ```python | ||
|
|
||
| class Solution: |
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.
l62の方が良かったと思います。
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.
確かに自分もどれを選ぶかを選ぶならl62のやつで書くかもです。(今回はStep1の書き直しという感じで書いてみました)
やり直しとかも見てくださりありがとうございます🙇
kazukiii
left a comment
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.
見ました。コメントのあるところ以外は良さそうに思いました。
| 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 |
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.
sum_so_farをcall stackに積まないで、nonlocalとして扱う書き方もありますね。その場合は、一歩戻るときに sum_so_far -= node.val を入れてあげないとですね。
| def search_target_sum(sum_so_far, node: Optional[TreeNode]): | ||
| nonlocal has_target | ||
| if not node: | ||
| return |
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.
if has_target: return
で枝狩りしておくと、ツリー全体を舐めなくて済みますね。
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.
あ、書いた時頭が混乱していましたが、これはL111のreturnとは別で、探索をかなりスルーできますね。(逆にL111はその後すぐNoneのノードが来るのでreturnする意味そんなにないですね)
ありがとうございます
https://leetcode.com/problems/path-sum/description/
Given the root of a binary tree and an integer targetSum, return true if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum.
A leaf is a node with no children.