diff --git a/2. Add Two Numbers.md b/2. Add Two Numbers.md new file mode 100644 index 0000000..3ff22a5 --- /dev/null +++ b/2. Add Two Numbers.md @@ -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]: + 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): + 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 + 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 + + 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 +``` + +- 指摘反映まで数日、期間が空いたがスムーズに書けたので、腹落ちしている書き方なのだと思う。