Conversation
| prev = dummy | ||
| current = head | ||
| while current: | ||
| while current.next and current.val == current.next.val: |
There was a problem hiding this comment.
これ、とりあえず、while 突入して、あとから何が起きたかを考えるの、素直じゃない気がします。後でどうせ分岐するならば確認してから突入したほうが分かりやすくないですか。
There was a problem hiding this comment.
有難うございます。
while curr_node:
if not curr_node.next or curr_node.val != curr_node.next.val:
prev_node = prev_node.next
curr_node = curr_node.next
continueこんな感じで、今のノードと次のノードの値が異なる場合の判定を先に済ませる感じでしょうか。
同じノードを飛ばす処理の方に意識がいってしまって、このような構成になってしまったんだと思います。。
There was a problem hiding this comment.
同じような話で、
while curr_node and curr_node.next:
if curr_node.val != curr_node.next.val:
prev_node = prev_node.next
curr_node = curr_node.next
continueこっちの方が良いですかね。
| duplicated_value = current.val | ||
| continue | ||
|
|
||
| previous.next = ListNode(current.val) |
There was a problem hiding this comment.
ここで新たなノードを作っていますが、previous.next = currentにするとLinkedListの繋ぎ変え操作だけで行けると思います。
ただ、whileの抜けた部分でもprevious.next = currentする必要がありますが。
There was a problem hiding this comment.
有難うございます。
個人的にループの外で後始末したくないなという気持ちがありますが、オブジェクトを毎回生成するのも無駄ですよね。
previous.next = currentがないと、最後のノードの値が連続したようなケース(1 -> 2 -> 2 -> 2とか)でコケる感じですね。
There was a problem hiding this comment.
確かに私も抜けた後にprevious.next = currentするのはできればしたくないと思います。
ただ、新しいノードを作る方法だと空間計算量がO(N)になるのがデメリットかなと思います。
| previous = dummy | ||
| current = head |
There was a problem hiding this comment.
有難うございます!
文字数も減りますし、こちらの方が良いですね。
| if head.val == duplicated_val: | ||
| head = delete_duplicates_helper(head.next, head.val) | ||
| elif head.next and head.val == head.next.val: | ||
| head = delete_duplicates_helper(head.next, head.val) | ||
| else: | ||
| head.next = delete_duplicates_helper(head.next, None) | ||
|
|
||
| return head |
There was a problem hiding this comment.
early returnしちゃって
if head.val == duplicated_val:
return delete_duplicates_helper(head.next, head.val)
if head.next and head.val == head.next.val:
return delete_duplicates_helper(head.next, head.val)
head.next = delete_duplicates_helper(head.next, None)
return headするのはいかがでしょうか。
There was a problem hiding this comment.
有難うございます。
確かにこちらの方が条件ごとにシンプルに分かれていて読みやすい気がします。
今までearly returnが選択肢の候補に入ることがあまりなかったので、今後は意識してみようと思います。
変数名を修正したバージョンを追加(Step4)
再帰の実装をearly-return方式にアップデート
| prev_node = prev_node.next | ||
| else: | ||
| prev_node.next = curr_node.next | ||
| curr_node = curr_node.next |
There was a problem hiding this comment.
このStep 3は読みにくいと感じました。重複値がある場合とない場合の2つを意識して読み進める必要がありますよね。
There was a problem hiding this comment.
有難うございます。
#6 (comment)
こちらのご指摘も同様ですよね。
先に重複値がない場合を処理してしまって、後半で重複のある場合の処理をすることで、問題をシンプルにしていくイメージでしょうか。
新たにノードオブジェクトを生成しない形式で書き直し
|
odaさん、sakupan102さん、liquo-riceさん、レビューを有難うございました! |
https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/description/