-
Notifications
You must be signed in to change notification settings - Fork 0
2. Add Two Numbers.md #4
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?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
|
||
URL: https://leetcode.com/problems/add-two-numbers/description/ | ||
|
||
# Step 1 | ||
|
||
- 実装時間: 10分 | ||
- 時間計算量: O(max(n,m)) | ||
- 空間計算量: O(1) | ||
- `Optional`の使い方だけ確認して解き始めた。 | ||
|
||
```python | ||
class Solution: | ||
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]: | ||
sentinel = ListNode(0,None) | ||
node = sentinel | ||
carry = 0 | ||
while l1 is not None or l2 is not None or carry > 0: | ||
node.next = ListNode(0, None) | ||
node = node.next | ||
if l1 is not None: | ||
node.val += l1.val | ||
l1 = l1.next | ||
if l2 is not None: | ||
node.val += l2.val | ||
l2 = l2.next | ||
node.val += carry | ||
if node.val >= 10: | ||
node.val %= 10 | ||
carry = 1 | ||
else: | ||
carry = 0 | ||
return sentinel.next | ||
|
||
``` | ||
|
||
# Step 2 | ||
|
||
- node.valの初期値をcarryにする。 `carry = sum / 10`で計算できる。 | ||
|
||
- 空間計算量が間違えている。 | ||
- 答えの桁数に応じてNodeを増やしていくので、足し算の結果(和)`s`に対して`O(log s)`になる。 | ||
- 桁数に注目するなら、入力の桁数を`n, m`とすると`O(max(n, m))`。 | ||
|
||
- 別の書き方。 | ||
- 足すのとノードを動かすのを一緒にやるか、分けるかは好みですかね | ||
- ヘルパー関数。carryは0, 1で持っている。`sum = getValue(l1) + getValue(l2) + carry` | ||
|
||
```python | ||
class Solution: | ||
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]: | ||
sentinel = ListNode(0,None) | ||
node = sentinel | ||
carry = 0 | ||
while l1 is not None or l2 is not None or carry > 0: | ||
node.next = ListNode(carry, None) | ||
node = node.next | ||
if l1 is not None: | ||
node.val += l1.val | ||
l1 = l1.next | ||
if l2 is not None: | ||
node.val += l2.val | ||
l2 = l2.next | ||
carry = node.val // 10 | ||
node.val %= 10 | ||
return sentinel.next | ||
``` | ||
|
||
# Step 3 | ||
|
||
- 入力の桁数を`n, m`として、 | ||
- 時間計算量: O(max(n,m)) | ||
- 空間計算量: O(max(n,m)) | ||
|
||
```python | ||
class Solution: | ||
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. なんかうまく言語化できないんですけど、結構読みづらいなと思いました。 L90のnode.valに何が入るかを知るのに、以下の5ステップをちゃんと追わないといけなくてこの短い行数でも結構しんどかったです。
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. あとはループの中でいきなりnodeが進んで意味が変わるのもちょっと難しかったです。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ありがとうございます!率直なフィードバックありがたいです。 コメントを見て、やっぱり、読み手としは
の方がわかりやすいのかなと気づきました。Step4として書き直してみます。 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. https://discord.com/channels/1084280443945353267/1200089668901937312/1206180274442993694 |
||
sentinel = ListNode() | ||
node = sentinel | ||
carry = 0 | ||
while l1 is not None or l2 is not None or carry > 0: | ||
node.next = ListNode(carry, None) | ||
node = node.next | ||
if l1 is not None: | ||
node.val += l1.val | ||
l1 = l1.next | ||
if l2 is not None: | ||
node.val += l2.val | ||
l2 = l2.next | ||
carry = node.val // 10 | ||
node.val %= 10 | ||
return sentinel.next | ||
``` | ||
|
||
# Step 4 | ||
|
||
- コメントをいただいたので、以下を反映。 | ||
- 「足し算の結果の桁数を入れるよ」の意味が伝わるような変数を用意する。 | ||
- 素直に足し算処理はまとめて書く。Node作ったり進めたりするのは足し算の処理とごっちゃにしない | ||
|
||
```python | ||
class Solution: | ||
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]: | ||
def _get_value(node): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. inner function の関数名の先頭には _ を付けなくてよいと思います。 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. https://docs.python.org/3/tutorial/classes.html#private-variables
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://peps.python.org/pep-0008/#descriptive-naming-styles
|
||
if node is None: | ||
return 0 | ||
return node.val | ||
|
||
sentinel = ListNode(0, None) | ||
carry = 0 | ||
node = sentinel | ||
while l1 is not None or l2 is not None or carry > 0: | ||
sum = _get_value(l1) + _get_value(l2) + carry | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. |
||
carry = sum // 10 | ||
sum %= 10 | ||
|
||
node.next = ListNode(sum, None) | ||
node = node.next | ||
|
||
if l1 is not None: | ||
l1 = l1.next | ||
if l2 is not None: | ||
l2 = l2.next | ||
return sentinel.next | ||
``` | ||
|
||
# Step 5 | ||
|
||
- コメントをいただいたので、以下を反映。 | ||
- inner functionの関数名の`_`はなくす | ||
- builtin functionと変数名の重複は避ける。 | ||
- デフォルト値で初期化させる。 | ||
|
||
```python | ||
class Solution: | ||
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]: | ||
def get_value(node): | ||
if node is None: | ||
return 0 | ||
return node.val | ||
|
||
sentinel = ListNode() | ||
node = sentinel | ||
carry = 0 | ||
while l1 is not None or l2 is not None or carry > 0: | ||
sum_value = get_value(l1) + get_value(l2) + carry | ||
carry = sum_value // 10 | ||
sum_value %= 10 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. ありがとうございます! 以下、自分の調べたメモ:
|
||
|
||
node.next = ListNode(sum_value) | ||
node = node.next | ||
|
||
if l1 is not None: | ||
l1 = l1.next | ||
if l2 is not None: | ||
l2 = l2.next | ||
return sentinel.next | ||
``` | ||
|
||
- 指摘反映まで数日、期間が空いたがスムーズに書けたので、腹落ちしている書き方なのだと思う。 |
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.
,
のあとにスペースを空けることをおすすめいたします。また、第一引数のデフォルト値が 0、第二引数のデフォルト値が None のため、引数は渡さなくてよいと思います。