-
Notifications
You must be signed in to change notification settings - Fork 0
2. add two numbers #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,153 @@ | ||
| step1 | ||
| 解く問題:https://leetcode.com/problems/add-two-numbers/description/ | ||
| 1つ目のノードには1の位、2つ目のノードには10の位、・・・と格納されている。 | ||
| 1つ目のノードの値+2つ目のノードの値×10+3つ目のノードの値×100というように計算してそれぞれのリストの値を求める。 | ||
| それらを足した数を1の位から格納していく。 | ||
| 割り算の余りを考えれば、各桁の数を取り出せそう。 | ||
| n÷10の余りをkとする。 | ||
| kが1の位の数 | ||
| n = (n-k)/10とすれば繰り返し処理にできそう。 | ||
| ここまで思いついたことをコードにしてみる。 | ||
| ある数を1の位からノードにして格納する方法で悩んでいる。 | ||
| 数字は取り出せるが、次のノードへの連結が難しい。 | ||
| dummyを用意してそこを始点とすると上手くいきそう。 | ||
| とりあえず書いてみた。 | ||
| sumで判定を行っているので、一番最初のsumが0の時にリストが返されないことに気づいた。 | ||
| sumが0の時の処理を加えた。 | ||
| とりあえず実行できた。 | ||
| ```python3 | ||
| # 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]: | ||
| l1_number = 0 | ||
| l2_number = 0 | ||
|
|
||
| #l1の数字を求める | ||
| node = l1 | ||
| digit = 1 | ||
| while node is not None: | ||
| l1_number += node.val * digit | ||
| digit = digit * 10 | ||
| node = node.next | ||
|
|
||
| #l2の数字を求める | ||
| node = l2 | ||
| digit = 1 | ||
| while node is not None: | ||
| l2_number += node.val * digit | ||
| digit = digit * 10 | ||
| node = node.next | ||
|
|
||
| sum = l1_number + l2_number | ||
|
|
||
| if sum == 0: | ||
| node = ListNode(0) | ||
| return node | ||
|
|
||
| dummy = ListNode() | ||
| last_added_node = dummy | ||
| #sumの1の位から順にリストを作成する | ||
| while sum != 0: | ||
| node_val = sum % 10 | ||
| sum = (sum - node_val) // 10 | ||
|
|
||
| node = ListNode(node_val) | ||
| last_added_node.next = node | ||
| last_added_node = node | ||
|
|
||
| return dummy.next | ||
| ``` | ||
|
|
||
| step2 | ||
| 他の人のコードを見てみた。 | ||
| 多くの人が同じ桁のノードごとに計算を行っていた。 | ||
| なぜこのやり方でやるのかわからない。 | ||
| と思っていたら、araiさんの動画で説明があった。 | ||
| 動画でこの問題は大きな数字を扱うためにこのような操作を行っているらしい。 | ||
| 確かに最初に数字を計算する手法では、もしノード数が100だった場合に100桁の数字を扱うことになる。 | ||
| 100桁の数字は64bitで表現できない。他の言語ではこのアルゴリズムは使えない。 | ||
| c++で上手くいかなかった人がいた。https://github.com/5103246/LeetCode_Arai60/pull/5/commits/475690037f777b12e6f01dfd3335fd7c2fbcb5db | ||
| また、大きな数字の割り算を何度も行うことになる。 | ||
| 同じ桁のノードごとに演算を行う方が良いと思った。 | ||
| 極端な入力などを自分の頭で動かしてみるなどすれば、大きな数字を扱えないことに気づけたのかもしれない。 | ||
| Pythonは何桁まで使えるのか気なった。 | ||
| https://docs.python.org/ja/3.14/library/stdtypes.html#numeric-types-int-float-complex | ||
| 整数には精度の制限がないらしい | ||
| それをどのように実現しているのかgeminiに聞いた。 | ||
| この問題と同じように桁ごとに分割して格納しているらしい。2^30進数らしい。 | ||
| Pythonの整数型の実装コード https://github.com/python/cpython/blob/main/Objects/longobject.c | ||
| そのため桁ごとに計算する方針で解くことにする。 | ||
| 各桁の足し算を行う際に、数字を記録しておいて後で、まとめて足すコード https://github.com/resumit30minutes/leetcode-arai60-practice/blob/7c31041bc3f35ffa52f6637ef74afaf9d644f4a0/leetcode/add_two_numbers/step4.py | ||
| 順に足していっているコード https://github.com/05ryt31/leetcode/blob/main/2-add-two-numbers/step3.py | ||
| まとめて足すコードの方が、足し算の式が一本にまとまっており何をしているのかわかりやすかったので、こちらのやり方でコードを書くことにする。 | ||
| divmodという関数があるらしい。名前の通り、入力した2つの数のdivとmodを返す。 | ||
| ```python3 | ||
| # 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() | ||
| fixed_tail = dummy | ||
| carry = 0 | ||
|
|
||
| while l1 is not None or l2 is not None or carry != 0: | ||
| node1_val = 0 | ||
| if l1 is not None: | ||
| node1_val = l1.val | ||
| l1 = l1.next | ||
|
|
||
| node2_val = 0 | ||
| if l2 is not None: | ||
| node2_val = l2.val | ||
| l2 = l2.next | ||
|
|
||
| total = node1_val + node2_val + carry | ||
|
|
||
| digit = total % 10 | ||
| fixed_tail.next = ListNode(digit) | ||
| fixed_tail = fixed_tail.next | ||
| carry = total // 10 | ||
|
|
||
| return dummy.next | ||
| ``` | ||
| step3 | ||
| ```python3 | ||
| # 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() | ||
| fixed_tail = dummy | ||
| carry = 0 | ||
|
|
||
| while l1 is not None or l2 is not None or carry != 0: | ||
| node1_val = 0 | ||
| if l1 is not None: | ||
| node1_val = l1.val | ||
| l1 = l1.next | ||
|
|
||
| node2_val = 0 | ||
| if l2 is not None: | ||
| node2_val = l2.val | ||
| l2 = l2.next | ||
|
|
||
| total = node1_val + node2_val + carry | ||
|
|
||
| digit = total % 10 | ||
| fixed_tail.next = ListNode(digit) | ||
| fixed_tail = fixed_tail.next | ||
|
|
||
| carry = total // 10 | ||
|
|
||
| return dummy.next | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| step1 | ||
| 解く問題:https://leetcode.com/problems/add-two-numbers/description/ | ||
| 1つ目のノードには1の位、2つ目のノードには10の位、・・・と格納されている。 | ||
| 1つ目のノードの値+2つ目のノードの値×10+3つ目のノードの値×100というように計算してそれぞれのリストの値を求める。 | ||
| それらを足した数を1の位から格納していく。 | ||
| 割り算の余りを考えれば、各桁の数を取り出せそう。 | ||
| n÷10の余りをkとする。 | ||
| kが1の位の数 | ||
| n = (n-k)/10とすれば繰り返し処理にできそう。 | ||
| ここまで思いついたことをコードにしてみる。 | ||
| ある数を1の位からノードにして格納する方法で悩んでいる。 | ||
| 数字は取り出せるが、次のノードへの連結が難しい。 | ||
| dummyを用意してそこを始点とすると上手くいきそう。 | ||
| とりあえず書いてみた。 | ||
| sumで判定を行っているので、一番最初のsumが0の時にリストが返されないことに気づいた。 | ||
| sumが0の時の処理を加えた。 | ||
| とりあえず実行できた。 | ||
|
|
||
| step2 | ||
| 他の人のコードを見てみた。 | ||
| 多くの人が同じ桁のノードごとに計算を行っていた。 | ||
| なぜこのやり方でやるのかわからない。 | ||
| と思っていたら、araiさんの動画で説明があった。 | ||
| 動画でこの問題は大きな数字を扱うためにこのような操作を行っているらしい。 | ||
| 確かに最初に数字を計算する手法では、もしノード数が100だった場合に100桁の数字を扱うことになる。 | ||
| 100桁の数字は64bitで表現できない。他の言語ではこのアルゴリズムは使えない。 | ||
| c++で上手くいかなかった人がいた。https://github.com/5103246/LeetCode_Arai60/pull/5/commits/475690037f777b12e6f01dfd3335fd7c2fbcb5db | ||
| また、大きな数字の割り算を何度も行うことになる。 | ||
| 同じ桁のノードごとに演算を行う方が良いと思った。 | ||
| 極端な入力などを自分の頭で動かしてみるなどすれば、大きな数字を扱えないことに気づけたのかもしれない。 | ||
| Pythonは何桁まで使えるのか気なった。 | ||
| https://docs.python.org/ja/3.14/library/stdtypes.html#numeric-types-int-float-complex | ||
| 整数には精度の制限がないらしい | ||
| それをどのように実現しているのかgeminiに聞いた。 | ||
| この問題と同じように桁ごとに分割して格納しているらしい。2^30進数らしい。 | ||
| Pythonの整数型の実装コード https://github.com/python/cpython/blob/main/Objects/longobject.c | ||
| そのため桁ごとに計算する方針で解くことにする。 | ||
| 各桁の足し算を行う際に、数字を記録しておいて後で、まとめて足すコード https://github.com/resumit30minutes/leetcode-arai60-practice/blob/7c31041bc3f35ffa52f6637ef74afaf9d644f4a0/leetcode/add_two_numbers/step4.py | ||
| 順に足していっているコード https://github.com/05ryt31/leetcode/blob/main/2-add-two-numbers/step3.py | ||
| まとめて足すコードの方が、足し算の式が一本にまとまっており何をしているのかわかりやすかったので、こちらのやり方でコードを書くことにする。 | ||
| divmodという関数があるらしい。名前の通り、入力した2つの数のdivとmodを返す。 | ||
|
|
||
| step3 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| ```python3 | ||
| # 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]: | ||
| l1_number = 0 | ||
| l2_number = 0 | ||
|
|
||
| #l1の数字を求める | ||
| node = l1 | ||
| digit = 1 | ||
| while node is not None: | ||
| l1_number += node.val * digit | ||
| digit = digit * 10 | ||
| node = node.next | ||
|
|
||
| #l2の数字を求める | ||
| node = l2 | ||
| digit = 1 | ||
| while node is not None: | ||
| l2_number += node.val * digit | ||
| digit = digit * 10 | ||
| node = node.next | ||
|
|
||
| sum = l1_number + l2_number | ||
|
|
||
| if sum == 0: | ||
| node = ListNode(0) | ||
| return node | ||
|
|
||
| dummy = ListNode() | ||
|
Comment on lines
+30
to
+34
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. 個人的にはこの初期値は使わないのでなんでもいいという意味合いだと思うので、上とはものが違うというのでいいかと思います。 |
||
| last_added_node = dummy | ||
| #sumの1の位から順にリストを作成する | ||
| while sum != 0: | ||
| node_val = sum % 10 | ||
| sum = (sum - node_val) // 10 | ||
|
|
||
| node = ListNode(node_val) | ||
| last_added_node.next = node | ||
| last_added_node = node | ||
|
|
||
| return dummy.next | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| ```python3 | ||
| # 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() | ||
| fixed_tail = dummy | ||
| carry = 0 | ||
|
|
||
| while l1 is not None or l2 is not None or carry != 0: | ||
| node1_val = 0 | ||
| if l1 is not None: | ||
| node1_val = l1.val | ||
| l1 = l1.next | ||
|
|
||
| node2_val = 0 | ||
| if l2 is not None: | ||
| node2_val = l2.val | ||
| l2 = l2.next | ||
|
|
||
| total = node1_val + node2_val + carry | ||
|
|
||
| digit = total % 10 | ||
| fixed_tail.next = ListNode(digit) | ||
| fixed_tail = fixed_tail.next | ||
| carry = total // 10 | ||
|
|
||
| return dummy.next | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| step3 | ||
| ```python3 | ||
| # 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]: | ||
|
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. どうやら両方が None である可能性はこの問題では気にしなくて良いようですが、来たら None が返りますね。 |
||
| dummy = ListNode() | ||
| fixed_tail = dummy | ||
| carry = 0 | ||
|
|
||
| while l1 is not None or l2 is not None or carry != 0: | ||
| node1_val = 0 | ||
| if l1 is not None: | ||
| node1_val = l1.val | ||
| l1 = l1.next | ||
|
|
||
| node2_val = 0 | ||
| if l2 is not None: | ||
| node2_val = l2.val | ||
| l2 = l2.next | ||
|
|
||
| total = node1_val + node2_val + carry | ||
|
|
||
| digit = total % 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. 今回は10で割ったあまりで、今回の解法でいくと次のfixed_tailのvalだと思うので、それが伝わる命名の
Owner
Author
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. 確かにvalをつけた方が意味が分かりやすいですね。勉強になります。 |
||
| fixed_tail.next = ListNode(digit) | ||
| fixed_tail = fixed_tail.next | ||
|
|
||
| carry = total // 10 | ||
|
|
||
| return dummy.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を特別扱いする必要がありますね。