Skip to content

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
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
92 changes: 92 additions & 0 deletions 2. Add Two Numbers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@

URL: https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/description/

Choose a reason for hiding this comment

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

全然関係ないですが、リンク違います。


# 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)
Copy link

Choose a reason for hiding this comment

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

, のあとにスペースを空けることをおすすめいたします。

また、第一引数のデフォルト値が 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]:

Choose a reason for hiding this comment

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

なんかうまく言語化できないんですけど、結構読みづらいなと思いました。

L90のnode.valに何が入るかを知るのに、以下の5ステップをちゃんと追わないといけなくてこの短い行数でも結構しんどかったです。

  • L81でnode.nextにListNode(carry, None)でcarryが初期値として渡され
  • L82でそれがnodeに代入されて
  • L84でl1.valで足されて
  • L87でl2.valが足されて
  • 最後にL90で10で割った余りが入ってくる

Choose a reason for hiding this comment

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

あとはループの中でいきなりnodeが進んで意味が変わるのもちょっと難しかったです。

Copy link
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます!率直なフィードバックありがたいです。

コメントを見て、やっぱり、読み手としはsum = getValue(l1) + getValue(l2) + carryのような、

  • 「足し算の結果の桁数を入れるよ」の意味が伝わるような変数を用意する。
  • 素直に足し算処理はまとめて書く。Node作ったり進めたりするのは足し算の処理とごっちゃにしない。

の方がわかりやすいのかなと気づきました。Step4として書き直してみます。

Choose a reason for hiding this comment

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

そうですね。変数は不変な方が読む認知負荷が低いと思います。

Copy link

Choose a reason for hiding this comment

The 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
```