-
Notifications
You must be signed in to change notification settings - Fork 0
82. Remove Duplicates from Sorted List II #1
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,66 @@ | ||
|
|
||
| ## step1: | ||
| まず順番にノードを探索していって、head.valがhead.next.valと一致していればそれは重複したノードなのでそれらが消えるまでheadを進めていく。もしhead.valがhead.next.valでなければそれはdistinctなので答えで返すnodeとして追加するという方針で行く。しかし返すべき値をresとしてどのようにres自身に代入するか迷ったので、get_distinct_listという帰納関数を作りボトムアップでdistinctな連結リストを得て返すという方法を取った。 | ||
|
|
||
| ### code | ||
| ```python | ||
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
|
|
||
| def get_distinct_list(head_arg): | ||
|
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. _arg は、外側の head と被らないようにするための接尾辞でしょうか。引数の名前を node にすると、外側の head と被らないと思いました。 |
||
| if not head_arg or not head_arg.next: | ||
| return head_arg | ||
| if head_arg.val == head_arg.next.val: | ||
| while head_arg.next and head_arg.val == head_arg.next.val: | ||
| head_arg = head_arg.next | ||
| head_arg = head_arg.next | ||
| return get_distinct_list(head_arg) | ||
|
|
||
| head_arg.next = get_distinct_list(head_arg.next) | ||
| return head_arg | ||
|
|
||
| return get_distinct_list(head) | ||
| ``` | ||
|
|
||
| ## step2: | ||
| get_distinct_listがやっていることとdeleteDuplicatesがやってることが同じだと気づいたのでdeleteDuplicates内でのget_distinct_listの宣言をやめてdeleteDuplicatesの帰納的呼び出しを行うことにした。 | ||
|
|
||
| ### code | ||
| ```python | ||
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
|
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. 関数宣言の次の行に空行を入れるのは、あまり見ないように思います。趣味の範囲かもしれません。 |
||
| if not head or not head.next: | ||
| return head | ||
|
|
||
| if head.val == head.next.val: | ||
| while head.next and head.val == head.next.val: | ||
| head = head.next | ||
| head = head.next | ||
|
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. head はリンクトリストの先頭のノードを表す単語です。そのため、 head が動いていくというのは、違和感を感じました。一旦 node 等の変数に格納し、それを動かしていくほうが自然だと思います。 |
||
| return self.deleteDuplicates(head) | ||
|
|
||
| head.next = self.deleteDuplicates(head.next) | ||
| return head | ||
|
|
||
| ``` | ||
|
|
||
|
|
||
| ## step3: | ||
| duplicateだった場合に最後head = head.nextとやってるがそのままhead.nextを代入すればいいと気づいたのでhead = head.nextを消した。 | ||
|
|
||
| ### code | ||
| ```python | ||
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
| if not head or not head.next: | ||
| return head | ||
|
|
||
| if head.val == head.next.val: | ||
| while head.next and head.val == head.next.val: | ||
| head = head.next | ||
| return self.deleteDuplicates(head.next) | ||
|
|
||
| head.next = self.deleteDuplicates(head.next) | ||
| return head | ||
|
|
||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # Definition for singly-linked list. | ||
| # class ListNode: | ||
| # def __init__(self, val=0, next=None): | ||
| # self.val = val | ||
| # self.next = next | ||
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
|
|
||
| def get_distinct_list(head_arg): | ||
| if not head_arg or not head_arg.next: | ||
| return head_arg | ||
| if head_arg.val == head_arg.next.val: | ||
| while head_arg.next and head_arg.val == head_arg.next.val: | ||
| head_arg = head_arg.next | ||
| head_arg = head_arg.next | ||
| return get_distinct_list(head_arg) | ||
|
|
||
| head_arg.next = get_distinct_list(head_arg.next) | ||
| return head_arg | ||
|
|
||
| return get_distinct_list(head) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # Definition for singly-linked list. | ||
| # class ListNode: | ||
| # def __init__(self, val=0, next=None): | ||
| # self.val = val | ||
| # self.next = next | ||
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
|
|
||
| if not head or not head.next: | ||
| return head | ||
|
|
||
| if head.val == head.next.val: | ||
| while head.next and head.val == head.next.val: | ||
| head = head.next | ||
| head = head.next | ||
| return self.deleteDuplicates(head) | ||
|
|
||
| head.next = self.deleteDuplicates(head.next) | ||
| return head |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Definition for singly-linked list. | ||
| # class ListNode: | ||
| # def __init__(self, val=0, next=None): | ||
| # self.val = val | ||
| # self.next = next | ||
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
| if not head or not head.next: | ||
| return head | ||
|
|
||
| if head.val == head.next.val: | ||
| while head.next and head.val == head.next.val: | ||
| head = head.next | ||
| return self.deleteDuplicates(head.next) | ||
|
|
||
| head.next = self.deleteDuplicates(head.next) | ||
| return head |
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.
ほかの方が書かれたコードは読まれましたでしょうか?もしまだであれば、読まれることをお勧めいたします。また、読んだ際は、読んだソースコードのリンクと読んだときの所感を添えると、レビューワーにとって有益な情報となると思います。
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.
レビューして頂きありがとうございます!
他の方のコードも読んでみたのでメモ感覚で所感を書いてみます。
rimokem/arai60#4
こちらはwhile文を用いてポインタ操作で解いていて、再帰関数と比べてスタックオーバーフローの危険性がないのがGood point。気になったのはduplicatesがなくなったノードリストの一番最後のノードをtailとだけ変数で表していて、なんの後尾を表しているのかぱっと見わかりづらい。自分だったらno_duplicates_tailのように命名すると思う。
Zun-U/coding-practice-mochi0123#4
step1の方針では配列を別に作るというやり方を提案していたが、そうすると空間計算量がO(N)に増えてしまう。step3, 4を見るとPythonと比べると非常にコードが簡潔になっているが、dummyの役割のものにheadを紐付けることでprevNodeを軸にポインタ操作を行いより直感的なソースコードになっている。