Conversation
| # self.next = next | ||
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
| dummy = ListNode(0, head) |
There was a problem hiding this comment.
コメントありがとうございます。
確かにそちらの方が意味が分かりやすいですね。
参考にさせていただきます。
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
| dummy = ListNode(0, head) | ||
| unique = dummy | ||
| scan = head |
There was a problem hiding this comment.
scanという単語は、https://dictionary.cambridge.org/dictionary/english/scan によれば、全体をくまなくみること、みる動作を意味するみたいです。
なので、scan自体は
node = head
while node is not None:
...
node = node.nextという全体の構造を意味していると感じます。関数名としては適切かもしれませんが、scanしている対象はListNodeなので、nodeでいいと思います。
There was a problem hiding this comment.
コメントありがとうございます。
確かに見ているのはひとつひとつのnodeなのでnodeとする方が良いですね。
| if scan.val == scan.next.val: | ||
| while scan.next and scan.val == scan.next.val: | ||
| scan.next = scan.next.next | ||
| unique.next = scan.next | ||
| else: | ||
| unique.next = scan | ||
| unique = scan | ||
|
|
||
| scan = sca.next |
There was a problem hiding this comment.
自分ならここの部分は以下のように書きます。
| if scan.val == scan.next.val: | |
| while scan.next and scan.val == scan.next.val: | |
| scan.next = scan.next.next | |
| unique.next = scan.next | |
| else: | |
| unique.next = scan | |
| unique = scan | |
| scan = sca.next | |
| if scan.val != scan.next.val: | |
| unique.next = scan | |
| unique = unique.next | |
| scan = scan.next | |
| continue | |
| duplicated_value = scan.val | |
| while scan and scan.val == duplicated_value: | |
| scan = scan.next | |
| unique.next = scan |
There was a problem hiding this comment.
日本語でこの解法を説明する時に、「scan.valとscan.next.valの値が違うならuniqueにscanを追加して、unique, scan進めます。同じなら、scan.valがその値にならなくなるまでscanを進め、uniqueの末尾にscanを追加します」みたいに分けて書くのが自然だと思います。
L138のように合流させるような説明は読んでいて複雑に感じます。
There was a problem hiding this comment.
自分のコードは、
- if 重複があるのでその数字の部分はまるごと飛ばす
- else 重複がないのでそのnodeをuniqueに入れる
という風にみていて、どちらもif-else終了時に、
scanとscan.nextが違う数字だがscan.nextが重複がないかはまだ分からないという同じ状態
(初期状態でいうdummyとhead)になっているので次のnodeに進める処理を共通化させました。
しかし、確かにこちらの方が素直な実装に感じます。
ありがとうございます。参考にさせていただきます。
There was a problem hiding this comment.
4th.で実装してみました。
duplicated_valueと置いて比較することで重複している値を探して飛ばすというニュアンスがより伝わりやすくなる気がしますね。
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
| dummy_node = ListNode(0, head) | ||
| back_node = dummy_node |
There was a problem hiding this comment.
backよりfastとslowで前のnodeと後ろ(進みの遅い)nodeを表したらいいかなと思いました。
There was a problem hiding this comment.
コメントありがとうございます。
確かに他の皆さんのコードでもbackはあまり見なかった気がするので、一般的な名前にしたいと思います。
|
他の皆さんのように、それぞれの解法に対する計算量やどの解法が好みか、 |
| return dummy_node.next | ||
|
|
||
| ``` | ||
| まずdummy nodeを使うという発想がなかった |
There was a problem hiding this comment.
dummy を使わなくても分岐が少し増えるだけですね。使うことはいいんですが、使わないコードも書けると思って使ってください。
There was a problem hiding this comment.
コメントありがとうございます。
head node が重複があるかどうかの分岐ですね。
テクニックを知らなかったから解けないではいけませんからそちらの場合でも実装しておきたいと思います。
There was a problem hiding this comment.
4th.で実装してみました。
すべて重複するnodeの場合headがなくなってしまうなど、気を付けなければならないことがあり勉強になりました。
問題:https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/description/