Skip to content
Merged
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
138 changes: 138 additions & 0 deletions 競技プロ就活部PR用/2. Add Two Numbers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
## whileによる解法
* 時間計算量: O(N)
* 空間計算量: O(N)

### 1回目 (14m25s)
* ビット演算で似た問題を解いていたので、指針は思いついた。
* 最初のノードの計算を特別扱いしているが、これは無くせそう。


```python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode((l1.val + l2.val) % 10)
dummy_head = dummy
carry = (l1.val + l2.val) // 10

current1 = l1
current2 = l2

if current1: current1 = current1.next
if current2: current2 = current2.next

while current1 or current2 or carry:
val1 = current1.val if current1 else 0
val2 = current2.val if current2 else 0

dummy.next = ListNode((val1 + val2 + carry) % 10)
dummy = dummy.next
carry = (val1 + val2 + carry) // 10

if current1: current1 = current1.next
if current2: current2 = current2.next

return dummy_head
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

dummy が使う値ならば dummy という名称はちょっとずれている気がしますね。

```

### 2回目
* 1回目の計算の特別扱いを修正。
* dummyの初期化時に0を明示しなくても良さそう。
```python
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode()
dummy_head = dummy
carry = 0
current1 = l1
current2 = l2

while current1 or current2 or carry:
val1 = current1.val if current1 else 0
val2 = current2.val if current2 else 0

dummy.next = ListNode((val1 + val2 + carry) % 10)
dummy = dummy.next
carry = (val1 + val2 + carry) // 10

if current1: current1 = current1.next
if current2: current2 = current2.next

return dummy_head.next
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

こっちを dummy と呼ぶのは自然でしょう。

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.

なるほどです。ありがうございます。確かに、1個目はdummyというより、added_headとかが良いですね。意識できていなかったので、覚えておきます。

```


### 3回目
他参加者の参考になった点として、
* val1 = current1.val if current1 else 0の部分をget_valueとして関数化
* dummyの変数名を代わりにsentinelにする。
* totalでval1 + val2 + carryを変数化
を採用してみる。

```python
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
def get_value(node: Optional[ListNode]) -> int:
if node is None:
return 0
return node.val

sentinel = ListNode()
sentinel_head = sentinel
carry = 0

while l1 or l2 or carry:
value1 = get_value(l1)
value2 = get_value(l2)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

私ならvalue1, value2 = get_value(l1), get_value(l2)と一行で書きたくなります


total = value1 + value2 + carry
sentinel.next = ListNode(total % 10)
sentinel = sentinel.next
carry = total // 10

if l1: l1 = l1.next
if l2: l2 = l2.next

return sentinel_head.next
```


## 再帰による解法
* 比較的すんなり書き換えられた。

```python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
def get_value(node: Optional[ListNode]) -> int:
if node is None:
return 0
return node.val
Comment on lines +116 to +118
Copy link
Copy Markdown

@seal-azarashi seal-azarashi Jul 31, 2024

Choose a reason for hiding this comment

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

三項演算子にしても良いかなと思いました。Python の記法は独特で、嫌いだと言っている人も見たことがありますが、処理を英語で読み上げているような感じがして私は結構好きです。

Suggested change
if node is None:
return 0
return node.val
return node.val if node else 0

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.

有難うございます。特に考えずこの書き方していましたが、三項演算子のほうが自分的にも見やすいです。
Python の記法は独特で、嫌いだと言っている人も見たことがあります
存じ上げなかったです。自分も特に違和感ないです。


def next_node(node: Optional[ListNode]) -> Optional[ListNode]:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

私はこの関数名をmoveNodeとしていましたが、moveしない場合があるのでnext_nodeの方が良さそうですね

if node is None:
return None
return node.next

def _add_two_numbers_helper(node1: Optional[ListNode] , node2: Optional[ListNode], carry: int) -> Optional[ListNode]:
if not (node1 or node2 or carry):
return None

value1 = get_value(node1)
value2 = get_value(node2)
total = value1 + value2 + carry
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

https://github.com/Mike0121/LeetCode/pull/41/files#r1695305381
と指摘内容が被りますが
value1,value2への代入をやめると、余計な変数を増やさずに済むのでコードがシンプルになって読みやすくなりそうです。

Copy link
Copy Markdown
Owner Author

@Mike0121 Mike0121 Aug 1, 2024

Choose a reason for hiding this comment

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

有難うございます。確かにこの変数減らせますね。そっちの方が良さそうです。

node = ListNode(total % 10)
carry = total // 10
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

引数を書き換えているのが気になりました。

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.

ありがとうございます。そうですね、特にメリットないので中で別で変数作った方がわかりやすいですね。

node.next = _add_two_numbers_helper(next_node(node1), next_node(node2), carry)
return node

return _add_two_numbers_helper(l1, l2, 0)
```