-
Notifications
You must be signed in to change notification settings - Fork 0
Remove duplicates from sorted list ii #6
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,95 @@ | ||
| # 問題文 | ||
|
|
||
| # Step1 | ||
|
|
||
| かかった時間:20min | ||
|
|
||
| 思考ログ: | ||
| - 問題を理解する。 | ||
| - 前回とは異なり、重複があるものを”全て”削除する。 | ||
| - 入出力:ともに連結リスト | ||
| - 計算量:時間…O(N) 空間…O(1) | ||
| - ループの中で、2つのポインタの値を比較する。 | ||
| - 値が異なる場合は隣にいく。 | ||
| - 値が一致した場合は、先頭ノードだけ隣へ更新。再度比較して異なった場合は後方ノードを先頭に、先頭はその隣に移動。 | ||
| - 解けなかったので解法をみた。最初のノード(head)も重複している場合、それを削除する処理が必要。ダミーを使用することで先頭ノードの削除処理とそれ以外のノードの削除処理を同じ方法で扱える。ダミーを置くことに気づけなかった。 | ||
| ```python | ||
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
| dummy = ListNode(0) | ||
| dummy.next = head | ||
| previous_node = dummy | ||
| current_node = head | ||
|
|
||
| while current_node: | ||
| while current_node.next and current_node.val == current_node.next.val: | ||
| current_node = current_node.next | ||
| if previous_node.next == current_node: | ||
|
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 文の条件が True のときと False のときのどちらの時に値が重複しているのか、直感的でないように感じました。また、変数を previous_node と current_node の 2 つ使うのではなく、 1 つだけにしたほうがシンプルだと感じました。以下のようなコードはいかがでしょうか? node = dummy
while node and node.next and node.next.next:
if node.next.val != node.next.next.val:
# 重複していない場合
# early return する。
node = node.next
continue
# 重複している場合
value = node.next.val
while node.next and node.next.val == value:
node.next = node.next.next
Owner
Author
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. たしかにご提示のコードのほうが直感的だなと感じました。 |
||
| previous_node = previous_node.next | ||
| else: | ||
| previous_node.next = current_node.next | ||
| current_node = current_node.next | ||
| return dummy.next | ||
| ``` | ||
|
|
||
| # Step2 | ||
| かかった時間:min | ||
|
|
||
| 思考ログ | ||
| - 他の方のコードやコメントを読む | ||
| - [型ヒントでnodeが自明](https://github.com/hrkh/leetcode/pull/5/files#r1676086915) | ||
| - [かといってcurrentという名前は諸説ある](https://github.com/canisterism/leetcode/pull/4#discussion_r1688679810) | ||
| - [マジックナンバー(意味のない数字)は避けるべき](https://github.com/goto-untrapped/Arai60/pull/43#discussion_r1695376875) | ||
| - nodeが自明なのはそうだなって思ったので名前からnodeを消して実装をしてみる。こっちのほうが見やすいかも | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
| dummy = ListNode(None) | ||
| dummy.next = head | ||
| previous = dummy | ||
| current = head | ||
|
|
||
| while current: | ||
|
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. currentの初期化時にcurrent = previous = dummyとしておくと、walrus演算子を使ってcurrent := current.nextと書くことができ、ループ変数を進める処理をわかりやすくできます(python3.8以降)
Owner
Author
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. walrus演算子で変数への代入と変数の使用を同時に行えるのですね。適切に使えるとコードをすっきりできそうだなと思いました。ありがとうございます。 |
||
| while current.next and current.val == current.next.val: | ||
|
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. 実際はO(n)でできているのですが、whileが二重になっているのでぱっと見O(n^2)になっていることがなんとなく気になります。二重whileを使わない方法としては、duplicatedなどのフラグを用意してやるとできると思います。 |
||
| current = current.next | ||
| if previous.next == current: | ||
|
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. Step1の指摘と類似ですが、ここの分岐は読み飛ばしが発生したかしていないかなので、もう少しわかりやすくできると嬉しいですね。前のwhileの条件と逆になるのが見にくいのかも?と思いました。 while current.next and current.val == current.next.val:
current = current.next
previous.next = current.next
if previous.next == current:
previous = previous.next
Owner
Author
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. ブロックがすくないこちらのほうが私も見やすいと感じました。 |
||
| previous = previous.next | ||
| else: | ||
| previous.next = current.next | ||
| current= current.next | ||
| return dummy.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. 最適解ではありませんが、自分はHashMapでカウントしていく解法でも解きました。
Owner
Author
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の長さに依存するのでn | ||
| - 基本:`head`が空ないし要素が単一のときに`head`を返す | ||
| - 再帰:重複があったときの処理 | ||
|
|
||
| ```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) | ||
| else: | ||
| head.next = self.deleteDuplicates(head.next) | ||
| return head | ||
| ``` | ||
|
|
||
| # Step3 | ||
| かかった時間: 3min | ||
|
|
||
| Step2のコードを書き直し⇒Subを何回かした。 | ||
|
|
||
|
|
||
| # Step 4 | ||
| - レビューを持って修正を行う | ||
|
|
||
| ```python | ||
|
|
||
|
|
||
| ``` | ||
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.
sentinel という単語を使うのも良いと思います。
hroc135/leetcode#4 (comment)