Skip to content

Add 83. Remove Duplicates from Sorted List.md #3

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 3 commits 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
155 changes: 155 additions & 0 deletions 83. Remove Duplicates from Sorted List.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# step 1
```python3
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
node = head

while node is not None:
next_node = node.next
while next_node is not None and node.val == next_node.val:
next_node = next_node.next

node.next = next_node
node = node.next

return head
```

singly linked-listの問題は基本的には、
```python3
while node is not None:
# なんかする
node = node.next
```
となっていて、「なんかする」部分だけやることの言語化をサボらなければ解けそう。
Copy link

Choose a reason for hiding this comment

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

解法を思いつくこつはこれですね。
自然言語で身体性をもって考えるというのがわりと大切だと思っています。

Arial 60はデータ構造別、アルゴリズム別で大別されているので、最初の数問やれば、同じデータ構造やらアルゴリズムやらの後半問題は割とすんなり解ける気がする。

nをノードの数として、
- time complexity: O(n)
- space complexity: O(n) (Auxiliary space: O(1))

# step 2
参考
- https://github.com/katataku/leetcode/pull/2
- https://github.com/ichika0615/arai60/pull/3
- https://github.com/tarinaihitori/leetcode/pull/3

step 1で書いたものと同じ解法だが、`next_node`を定義せず、そのまま`node.next`を書き換えるものがあった。
step 1中で書いた構造の通り書きたい気持ちがあり、`node.next`の値がチラチラ変わるのは、読んでいて疲れそうだったので、`next_node`を定義してしまった方が読みやすいように思った。

また、次の値のノードに至るまでを関数化するものもあったが、このサイズのコードならそれをする必要はないように感じた。切り分けた処理を他で利用することも想定できなかった。

他の解法としてはには再帰を用いるもの、出現した値を全て保存しておき、それを用いて新たにLinked-listを作るものがあった。

再帰を使った解法
```python3
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None:
return None

next_node = self.deleteDuplicates(head.next)
if next_node is not None and head.val == next_node.val:
return next_node
else:
head.next = next_node
return head
```

再帰なし
```python3
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
node = head

while node is not None:
next_node = node.next
while next_node is not None and node.val == next_node.val:
next_node = next_node.next
node.next = next_node
node = node.next

return head
```

# step 3
再帰なし
```python3
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
node = head

while node is not None:
next_node = node.next
while next_node is not None and node.val == next_node.val:
next_node = next_node.next
node.next = next_node
node = node.next

return head
```

再帰あり
```python3
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None:
return None

next_node = self.deleteDuplicates(head.next)
if next_node is not None and head.val == next_node.val:
return next_node
else:

Choose a reason for hiding this comment

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

elseを消してインデントを下げると読みやすいかなと思いました

h1rosaka/arai60#2 (comment)

head.next = next_node
return head
```

# step 4
コメントまとめ
- インデントを下げられるときは下げる

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

while node is not None:
next_node = node.next
while next_node is not None and node.val == next_node.val:
next_node = next_node.next
node.next = next_node
node = node.next

return head
```

以下、追記

値に重複がある場合とない場合で明確に分けて書いた解法
```python
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
node = head
while node is not None:
if node.next is None or node.next.val != node.val:
node = node.next
continue

duplicated_value = node.val
while node.next is not None and node.next.val == duplicated_value:
node.next = node.next.next
return head
```

再帰・少し変えた書き方
```python
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None or head.next is None:
return head

if head.val != head.next.val:
head.next = self.deleteDuplicates(head.next)
return head
return self.deleteDuplicates(head.next)
```