Skip to content

Remove duplicate from sorted list2 #5

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions removeDuplicateFromSortedList2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Remove Duplicate from Sorted List 2

<https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/description/>

## step1 自力で解く

所要時間20分
10分ほど考えてわからなかったので動画を見た
前回も同じようなコードを書いたはずだが.valを参照しなければいけないということをずっと忘れていた

```python
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0)
dummy.next = head

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここはstep2以降のように、dummy = ListNode(0, head)で1行で書いてしまった方が個人的にはみやすいですね。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

すみません、こちらコメントにありました。

node = dummy
while node.next and node.next.next:
if node.next.val == node.next.next.val:
duplicateval = node.next.val
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

変数名の英単語は _ 区切りにすることをお勧めいたします。

https://peps.python.org/pep-0008/#function-and-variable-names

Function names should be lowercase, with words separated by underscores as necessary to improve readability.

https://google.github.io/styleguide/pyguide.html#316-naming

local_var_name

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while node.next and node.next.next and node.next.val == node.next.next.val:
    node.next.next = node.next.next.next
node.next = node.next.next

と、 2 個目以降の重複した要素を削除したあと、 1 個目の要素を削除するという方法もあります。

while node.next and node.next.val == duplicateval:
node.next = node.next.next
else:
node = node.next
return dummy.next

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

きれいで分かりやすいなと思いました。

```

## step2 読みやすくする&他の人の回答を見る
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

もう少し色々な回答を探して読んでみたほうがいい気がします。

ここで学習したいことは「他人のコードから意図を読み取ること」で、思ったよりも「色々な書き方があって」、「それぞれが変形で移り変われる」なと感じて欲しいです。
たとえば、
https://discord.com/channels/1084280443945353267/1226508154833993788/1246022270984392724
大変だったら、多分誰かがまとめていると思います。


下の方のを見てコードを書いた
<https://github.com/rinost081/LeetCode/pull/6/commits/23bf0657770cc81fad3b207a4733cc771397579b>

自分でやった時はnode.next.val == node.next.next.valを = で書いてしまいエラーになることがあった。この間違いはよくやってしまうので気をつけたい。

```python
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(-1,head)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

細かいですが、ListNode(-1, head)のように引数同士の間はスペースを開けた方が良さそうに思います。
pep8で引数同士の間のスペースの項目はパッと見つけられませんでしたが、多くの例でスペースが開けられています。
https://pep8-ja.readthedocs.io/ja/latest/

node = dummy

while node:
is_duplicate = False
while node.next and node.next.next and node.next.val == node.next.next.val:
is_duplicate = True
node.next = node.next.next

if is_duplicate:
node.next = node.next.next
else:
node = node.next

return dummy.next
```

step1 では `dummy = ListNode(0) dummy.next = head` と書いているが一行で代入できるのでそちらの方がわかりやすい

is_duplicateのTrue, Falseで判断する方が自分は読みやすかった。

`node.next = node.next.next`が二回出てきてるのが少し気持ち悪いが読みやすさ優先か。

ハッシュマップを用いる方法も見てみる
<https://github.com/Mike0121/LeetCode/commit/5e139d55ddb6685bd87cbd685538972058a61073>

defaultdictは知らなかったので以下を参考した
[Qiita defaultdictの使い方](https://qiita.com/xza/items/72a1b07fcf64d1f4bdb7)
初期値を設定しておき,dictにkeyが存在しない場合も要素を初期値として追加することができるdict
初期値には関数を用いることもできる

defaultdict(int)はdefaultdict(lambda:int())と同義で0を返す

```python
from collections import defaultdict
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None:
return head

current = head
value_counter = defaultdict(int)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こういうやり方もできるんですね。参考になりました。

while current:
value_counter[current.val] += 1
current = current.next

dummy = ListNode(0, head)
current = dummy
while current.next:
while current.next and value_counter[current.next.val] > 1:
current.next = current.next.next
if current.next:
current = current.next

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while current だと分岐が減ってよりスッキリしそうです。

while current:
    while current.next and value_counter[current.next.val] > 1:
        current.next = current.next.next
    current = current.next

return dummy.next
```

重複する要素を全て削除しなければいけない場合はハッシュマップだと二周しなければいけないから効率が悪い?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

効率が何を指しているかによる気がするので明確にできると良いかと思います。(ループ数なのか、計算量なのか)


## step3 3回連続エラーなしで解けるまでやる

```python
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(-1,head)
node = dummy

while node:
is_duplicate = False
while node.next and node.next.next and node.next.val == node.next.next.val:
is_duplicate = True
node.next = node.next.next

if is_duplicate:
node.next = node.next.next
else:
node = node.next

return dummy.next

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

個人的にstep1の方が分かりやすいと思いました。
最後の重複が取り除けないからif is_duplicate: としていると思うので、意味のつながりでいくと while句 + if句 と else句で分かれると思います。でも、if-else句 の方が書き方としてより強いつながりがあるのかなと想定して読んだので、そこのずれが気になりました。

```

step2での回答と同じものを書いた
変数名のタイプミスで動かないことが二回くらいあった