Skip to content

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
101 changes: 101 additions & 0 deletions lc2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"""step1
まずは繰り上がりがない単純な場合を考えてみる。
各ノードを参照して足すだけ
l1をreturnすることを考えてdummyを作成
桁が合わない場合のためにパディングをする、ただし効率的ではなさそう.
whileをl1 and l2ではなくl1 or l2にすればよい。ただしこの場合Noneを参照してエラーを起こしそう→起こしたのでそれに対するif分が必要
桁が合わない場合のケースが解けなかった。時間をかければ無理やり解けそうだが、20分を経過したのでやめる。
できなかったことは、l1とl2のどちらかが先にNoneに入るのでそれを阻止して足し算を続けること
解いた時に思ったのはflagをboolにするのではなく0か1を入れて常に足すというコードも書けるのではと思った。
"""
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
answer = l1
flag = False

Choose a reason for hiding this comment

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

Step1で解くときでもflagのような情報量がない変数名は避けたほうが良いかなと思います
自分で読んでて認知負荷が高くなるので、バグの温床になるかと



while l1 and l2:
if flag:
Copy link

Choose a reason for hiding this comment

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

インデントのスペースの数を統一することをお勧めいたします。

https://peps.python.org/pep-0008/#indentation

Use 4 spaces per indentation level.

https://google.github.io/styleguide/pyguide.html#34-indentation

Indent your code blocks with 4 spaces.

Copy link

Choose a reason for hiding this comment

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

l1.val += l2.val
if flag:
    l1.val += 1

と書いたほうがシンプルだと思います。

l1.val = l1.val + l2.val + 1
else:
l1.val = l1.val + l2.val

if l1.val > 9:
Copy link

Choose a reason for hiding this comment

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

flag = l1.val > 9
l1.val %= 10

と書いたほうがシンプルだと思います。

l1.val = l1.val % 10
flag = True
else:
flag = False

l1 = l1.next
l2 = l2.next

if flag:
l1.val = 1

return answer
"""step2
これまでみたいに長々と書かずに解けるものなのだと思ってstep1は途中で辞めたんですけど、別の関数を作ったり結構長めなコードを書いている人を見たので変な先入観は捨てます、、、
step1でやりたかった処理は以下の通り
時間計算量は0(n)
Copy link

Choose a reason for hiding this comment

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

0(n) → O(n)

空間計算量はO(n) 両者ともl1とl2で長さが大きい方をnとしている
"""
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
answer = ListNode(-1)

Choose a reason for hiding this comment

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

answerという変数名を使うことは避けたほうが良いと思います

初めてこのコードを読む人からすると、「この変数が一体何か」が関数の最後まで読まないとわかりません。
関数の先頭から読んでいって、理屈と意図がわかるようなコードを書くのが理想的かなと思います

この場合、sentinel, dummyなどが適切でしょうか

参考: hroc135/leetcode#15 (comment)

Copy link
Owner Author

Choose a reason for hiding this comment

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

LeetCodeのような問題に対する回答として、answerとつけてましたがその通りですね。ありがとうございます

Copy link

Choose a reason for hiding this comment

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

answer というからには return answer を期待するがそうではない、というのが抵抗感の一番の要因だと思っています。
意味が「答え」なのだからこれ自体が「足した答え」になると期待しますが、裏切られます。

answer_head = answer

Choose a reason for hiding this comment

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

同様に、ここはnodeなどで十分かなと。

carry = 0

while l1 or l2:
answer.next = ListNode()
answer = answer.next
Comment on lines +49 to +50

Choose a reason for hiding this comment

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

計算結果から新しいnodeを作成 -> 現在のお尻につけるのほうが自然じゃないでしょうか?


l1_val = l1.val if l1 else 0
l2_val = l2.val if l2 else 0

answer.val = l1_val + l2_val + carry

if answer.val > 9:
answer.val = answer.val % 10
carry = 1
else:
carry = 0
Comment on lines +55 to +61

Choose a reason for hiding this comment

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

Suggested change
answer.val = l1_val + l2_val + carry
if answer.val > 9:
answer.val = answer.val % 10
carry = 1
else:
carry = 0
sum = l1_val + l2_val + carry
answer.val = sum % 10
carry = sum // 10

でまとめられそうです。


l1 = l1.next if l1 else None
l2 = l2.next if l2 else None

if carry:
answer.next = ListNode(1)

return answer_head.next
"""
step3
2分50秒
"""
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
answer = ListNode(-1)
Copy link

Choose a reason for hiding this comment

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

dummy_head や sentinel という変数名を使われている方もいらっしゃいます。他の書かれたソースコードを読んで参考にしてみてください。

answer_head = answer
carry = 0

while l1 or l2:

Choose a reason for hiding this comment

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

ここにcarryの条件も入れれば最後のif carryを消せそうです

answer.next = ListNode()
answer = answer.next

l1_val = l1.val if l1 else 0
l2_val = l2.val if l2 else 0

answer.val = l1_val + l2_val + carry

if answer.val > 9:

Choose a reason for hiding this comment

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

carry = carry / 10などするとこの分岐を消せそうですね。

answer.val = answer.val % 10
carry = 1
else:
carry = 0

l1 = l1.next if l1 else None
l2 = l2.next if l2 else None

if carry:
answer.next = ListNode(1)

return answer_head.next