-
Notifications
You must be signed in to change notification settings - Fork 0
2. Add Two Numbers #7
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,111 @@ | ||
| ## step1 | ||
| - エレガントな解法は思いつかなかった | ||
| - 2つとも数字に直して、足して一番大きい桁から新しく、連結リストを作る方法しか思いつかなかった | ||
| - 一回書いてみる | ||
| - 最後小さい桁からheadに入れないといけないので合計の数字を文字列にして逆順で取り出す | ||
| - headを特別に処理したくないので、前回勉強したdummy.nextを使ってみた | ||
|
|
||
| ``` | ||
| def addTwoNumbers( | ||
| self, l1: Optional[ListNode], l2: Optional[ListNode] | ||
| ) -> Optional[ListNode]: | ||
| l1_toal = 0 | ||
| l2_toal = 0 | ||
|
|
||
| order = 0 | ||
| while l1: | ||
| l1_toal = l1_toal + l1.val * (10**order) | ||
| l1 = l1.next | ||
| order += 1 | ||
| order = 0 | ||
|
|
||
| while l2: | ||
| l2_toal = l2_toal + l2.val * (10**order) | ||
| l2 = l2.next | ||
| order += 1 | ||
|
|
||
| total = l1_toal + l2_toal | ||
|
|
||
| total_string = str(total) | ||
|
|
||
| dummy = ListNode() | ||
| node = dummy | ||
| for num in total_string[::-1]: | ||
| node.next = ListNode(int(num)) | ||
| node = node.next | ||
|
|
||
| return dummy.next | ||
| ``` | ||
|
|
||
| - 解いた後再度確認すると最初に読んだ際に問題を誤読していて、小さい桁から値が入ってくるのであれば普通に足していけばいい気がしてきた | ||
| - 出た順に足していった | ||
|
|
||
| ## step2 | ||
| - 変数名や処理も改善する部分がなさそうだと思ったので、他の人のコードを見てみる | ||
| - このくらいなら関数化しなくてもいいのかなと思った | ||
| - 関数化するなら合計の数字の繰り上げ処理のところとか、加算部分を関数化すると思う | ||
|
|
||
| - https://github.com/tNita/arai60/pull/6/files | ||
| ``` | ||
| [nits] | ||
| self に依存しないことを明示するために @staticmethod にする、というのもありそうです。 | ||
| ``` | ||
| - 勉強になった。selfに依存しない場合@staticmethodと明記する。普段の業務でTSで開発しているとstaticとよく書くがpythonで開発していないためあまり気にしたことがなかったので気にしたい | ||
| - 計算量書くのは良いので真似する | ||
|
|
||
| - https://github.com/Yoshiki-Iwasa/Arai60/pull/4 | ||
| - 私のコードではhasCarryとしてbooleanにしていたが、他の局面では繰り上がりは2以上になることがあるので今後の拡張性を意識してint型のcarryを使った方がいいかも? | ||
| - https://github.com/yus-yus/leetcode/pull/5/files/91f344d110d2dc8ce7982065314a25afec963cc9#r1944795971 | ||
| - `carry, digit = divmod(total, 10)` | ||
| - divmodという組み込み関数を知らなかった | ||
| - よくやる作業だし知らなくても関数名から意味がわかるので使っていきたい | ||
| - https://github.com/yus-yus/leetcode/pull/5 | ||
| - 下記のように書く | ||
| ``` | ||
| if not l1: l1 = ListNode(0) | ||
| if not l2: l2 = ListNode(0) | ||
| ``` | ||
| - 私の今のコードの場合whileの後の4行が不要になりスッキリするので採用する | ||
| - 他の人が見た場合でも伝わるはず | ||
| - https://github.com/SanakoMeine/leetcode/pull/6#discussion_r1901296375 | ||
| - この指摘はされないように気をつけたい | ||
| - 意図せず書いた場合はかなり印象悪くなりそう | ||
| - 数字や文字列は気にしなくてよくて、配列やobjectの場合は気にしているがある程度は慣れているので問題なさそうだが、LinkedListとかはかなり不安感ある | ||
| - https://github.com/mamo3gr/arai60/pull/5/files | ||
| - この方のコード見やすいのと他の方のコードについたコメントで気をつける点が全て反映されているような理想的なコードに見えた | ||
| - zipは見たことある,zip_longestは知らなかったが自分で書けるようになると今回のようなケースで便利 | ||
| - yieldは説明見てもあんまりピンとこないから怖くて使ってない | ||
| - 特にreturnや末尾で処理が止まらないところがいかつすぎる | ||
| - これ見たらイメージ湧いたかもしれない(https://qiita.com/shun_sakamoto/items/5f13fa96701ba3727dc0) | ||
| - これはyieldやzip_longestを使ってて上級者の書き方だと思った | ||
| ``` | ||
| def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]: | ||
| def generate_digits(l): | ||
| while l: | ||
| yield l.val | ||
| l = l.next | ||
| dummy = ListNode() | ||
| node = dummy | ||
| carry = 0 | ||
| for num1, num2 in zip_longest(generate_digits(l1), generate_digits(l2), fillvalue=0): | ||
| total = num1 + num2 + carry | ||
| node.next = ListNode(total % 10) | ||
| node = node.next | ||
| carry = total // 10 | ||
| if carry: | ||
| node.next = ListNode(carry) | ||
| return dummy.next | ||
| ``` | ||
|
|
||
| - 一旦下記を対応する | ||
| - 番兵 | ||
| - divmod | ||
| - carryをintにする | ||
| - 元の引数を変えない | ||
|
|
||
| 空間計算量: O(n) | ||
| 時間計算量: O(n) | ||
|
|
||
| ## step3 | ||
| - 何回も消して書くと頭のリソースの使用量がだんだん小さくできている感覚がある | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # | ||
| # @lc app=leetcode id=2 lang=python3 | ||
| # | ||
| # [2] Add Two Numbers | ||
| # | ||
|
|
||
| # @lc code=start | ||
| # 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_node = dummy | ||
| hasCarry = False | ||
|
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. 識別子が動詞の命令形もしくは三単現で始まっていると、関数名のように感じます。 step2 で既に修正されている通り、 carry で十分に伝わると思います。 |
||
|
|
||
| while l1 or l2 or hasCarry: | ||
| # 繰り上げのみ | ||
| if l1 is None and l2 is None: | ||
| total = 1 | ||
| elif l1 is None: | ||
| total = l2.val + 1 if hasCarry else l2.val | ||
| elif l2 is None: | ||
| total = l1.val + 1 if hasCarry else l1.val | ||
| else: | ||
| total = l1.val + l2.val + 1 if hasCarry else l1.val + l2.val | ||
|
|
||
| if total > 9: | ||
| hasCarry = True | ||
| total -= 10 | ||
| else: | ||
| hasCarry = False | ||
|
|
||
| fixed_node.next = ListNode(total) | ||
| fixed_node = fixed_node.next | ||
| if l1: | ||
| l1 = l1.next | ||
| if l2: | ||
| l2 = l2.next | ||
|
|
||
| return dummy.next | ||
|
|
||
|
|
||
| # @lc code=end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # | ||
| # @lc app=leetcode id=2 lang=python3 | ||
| # | ||
| # [2] Add Two Numbers | ||
| # | ||
|
|
||
| # @lc code=start | ||
| # 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_node = dummy | ||
|
Comment on lines
+17
to
+18
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. 同じ値を複数の変数に定義する場合は一行にまとめることが可能です。
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. ご指摘ありがとうございます。 |
||
|
|
||
| n1, n2 = l1, l2 | ||
| carry = 0 | ||
|
|
||
| while n1 or n2 or carry: | ||
| v1 = n1.val if n1 else 0 | ||
| v2 = n2.val if n2 else 0 | ||
|
|
||
| total = v1 + v2 + carry | ||
| carry, fixed_node_val = divmod(total, 10) | ||
| fixed_node.next = ListNode(fixed_node_val) | ||
| fixed_node = fixed_node.next | ||
|
|
||
| if n1: | ||
| n1 = n1.next | ||
| if n2: | ||
| n2 = n2.next | ||
|
|
||
| return dummy.next | ||
|
|
||
|
|
||
| # @lc code=end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # | ||
| # @lc app=leetcode id=2 lang=python3 | ||
| # | ||
| # [2] Add Two Numbers | ||
| # | ||
|
|
||
| # @lc code=start | ||
| # 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_node = dummy | ||
|
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. [nits]
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. ありがとうございます |
||
| carry = 0 | ||
|
|
||
| n1, n2 = l1, l2 | ||
|
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. 私は「引数は変更しない」ことをどこかで教わってきたのですが、必ずしもそうではなさそうです。例えば
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. ありがとうございます |
||
|
|
||
| while n1 or n2 or carry: | ||
| val1 = n1.val if n1 else 0 | ||
| val2 = n2.val if n2 else 0 | ||
|
|
||
| total = val1 + val2 + carry | ||
| carry, fixed_node_val = divmod(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. 私も 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が10進法の10であるというのは通じると思うのでこれでもいいかと思います。 |
||
| fixed_node.next = ListNode(fixed_node_val) | ||
| fixed_node = fixed_node.next | ||
|
|
||
| if n1: | ||
| n1 = n1.next | ||
| if n2: | ||
| n2 = n2.next | ||
|
|
||
| return dummy.next | ||
|
|
||
|
|
||
| # @lc code=end | ||
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.
変数名に lower_snake と lowerCamel が混ざっているのが気になりました。 lower_snake で統一することをお勧めいたします。
参考までにスタイルガイドへのリンクを共有いたします。
https://peps.python.org/pep-0008/#function-and-variable-names
なお、このスタイルガイドは“唯一の正解”というわけではなく、数あるガイドラインの一つに過ぎません。チームによって重視される書き方や慣習も異なります。そのため、ご自身の中に基準を持ちつつも、最終的にはチームの一般的な書き方に合わせることをお勧めします。