Create 82. Remove Duplicates from Sorted List II.md#4
Conversation
nanae772
left a comment
There was a problem hiding this comment.
お疲れ様です、ステップごとの改善の様子が分かりやすく読みやすかったです。
| def skip_duplicates(node): | ||
| while node.next is not None and node.next.val == node.val: | ||
| node.next = node.next.next | ||
| return node.next |
There was a problem hiding this comment.
単に重複を飛ばすだけならnode.nextを繋ぎかえていくのではなく、nodeを動かしていく方法のほうが分かりやすいかなと感じました。
nextを繋ぎ変えないのでこの関数の中では副作用が無くなり、そういった点でも良いかなと思います。
| def skip_duplicates(node): | |
| while node.next is not None and node.next.val == node.val: | |
| node.next = node.next.next | |
| return node.next | |
| def skip_duplicates(node): | |
| duplicated_val = node.val | |
| while node is not None and node.val == duplicated_val: | |
| node = node.next | |
| return node |
There was a problem hiding this comment.
修正後の方がいいですね。手抜きして関数化する前のコードをそのまま関数のコードに流用しておりました。
There was a problem hiding this comment.
nodeを動かしていく方法のほうが分かりやすいかなと感じました
同感です。修正後の方が私も良いと思います。
| while node.next is not None and node.next.val == node.val: | ||
| node.next = node.next.next | ||
| return node.next | ||
| dummy = ListNode(next = head) |
There was a problem hiding this comment.
PEP8ではキーワード引数への代入演算子の前後にはスペースを入れないことになっています。ご参考まで。
Don’t use spaces around the = sign when used to indicate a keyword argument, or when used to indicate a default value for an unannotated function parameter:
| while node.next is not None and node.next.val == node.val: | ||
| node.next = node.next.next | ||
| return node.next | ||
| dummy = ListNode(next = head) |
There was a problem hiding this comment.
inner functionの定義の後には空行を入れたいなと思いましたが、好みかもしれません。
There was a problem hiding this comment.
inner functionの定義の後には空行を入れたいなと思いました
同じように感じました
| node = dummy | ||
| while node.next is not None and node.next.next is not None: | ||
| if node.next.val == node.next.next.val: | ||
| copy = node.next |
There was a problem hiding this comment.
copyモジュールがあるので、copyという変数名は避けたほうがよいかもしれません。
| dummy = ListNode(next = head) | ||
| latest_unique = dummy | ||
| checking = latest_unique.next | ||
| while checking is not None and checking.next is not None: | ||
| if checking.val != checking.next.val: | ||
| latest_unique = checking | ||
| checking = latest_unique.next | ||
| continue | ||
| latest_unique.next = skip_duplicates(checking) | ||
| checking = latest_unique.next |
There was a problem hiding this comment.
latest_unique と checking の責務が混ざって見えます。
dummy/latest_unique は「確定済みリスト」、checking は「未確定リストの走査」に役割分担し、latest_unique.next は常に None に保つ不変条件にすると、意図が明確になります。下記のようにすると、ユニーク確定時だけ連結し、それ以外では確定側に触れません。
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
def skip_duplicates(node: ListNode) -> Optional[ListNode]:
while node.next is not None and node.next.val == node.val:
node.next = node.next.next
return node.next
dummy = ListNode() # 確定済みリストの番兵
latest_unique = dummy # その末尾。常に latest_unique.next は None
checking = head # 未確定側の走査ポインタ
while checking is not None:
# 直後が別値 or 末尾ならユニーク
if checking.next is None or checking.val != checking.next.val:
latest_unique.next = checking # 確定側に連結
latest_unique = checking # 末尾を更新
checking = checking.next # 未確定側を先に進める
latest_unique.next = None # 不変条件: ここで切断
else:
# 重複ブロックは確定側に触れずスキップ
checking = skip_duplicates(checking)
return dummy.nextThere was a problem hiding this comment.
ご指摘の通りlatest_uniqueとcheckingの役割を分け切れていなかったです。番兵というテクニックを初めて知りました。
|
|
||
| ``` | ||
| ## 2-2 | ||
| - 2-1のコードをさらに整理。参考にした議論はdiscordのリンクを保存してなかったので引用できないが、小田さんがいろいろ突っ込みを入れていて19個目のつっこみで条件式を色々と変形していたあたりを参考にした。 |
| dummy = ListNode(next = head) | ||
| node = dummy | ||
| while node.next is not None and node.next.next is not None: | ||
| if node.next.val == node.next.next.val: |
There was a problem hiding this comment.
一般にネストを浅くしたほうが読みやすくなる傾向があります。真偽を逆にして、ネストを浅くするとよいと思います。
if node.next.val != node.next.next.val:
continue
今回の問題: 82. Remove Duplicates from Sorted List II
次回の問題: 2. Add Two Numbers