From 22e34a72188c478176ff88d761525ce6b73f5e02 Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Tue, 13 Feb 2024 00:44:52 +0900 Subject: [PATCH 1/6] Create 82. Remove Duplicates from Sorted List II.md --- 82. Remove Duplicates from Sorted List II.md | 121 +++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 82. Remove Duplicates from Sorted List II.md diff --git a/82. Remove Duplicates from Sorted List II.md b/82. Remove Duplicates from Sorted List II.md new file mode 100644 index 0000000..85d8aba --- /dev/null +++ b/82. Remove Duplicates from Sorted List II.md @@ -0,0 +1,121 @@ +前回の問題と異なり重複がある場合は全てのノードを削除する必要がある。headノードも削除される可能性があるのでダミーノードを用意するのが良い。 +1回のループで答えのリストを作るのが難しかったので、重複のないノードをリストに詰めてその後、答えのリストを作成する流れで書いた。 + +1st + +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + unique_nodes = [] + current_node = head + while current_node: + if current_node.next and current_node.val == current_node.next.val: + current_value = current_node.val + while current_node and current_node.val == current_value: + current_node = current_node.next + continue + unique_nodes.append(current_node) + current_node = current_node.next + if not unique_nodes: + return None + sentinel = ListNode() + current_node = sentinel + for node in unique_nodes: + current_node.next = node + current_node = current_node.next + current_node.next = None + return sentinel.next +``` + +2nd + +重複を発見したら変えるな。2重ループ。 +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + sentinel = ListNode() + last_unique_node = sentinel + current_node = head + while current_node: + if current_node.next and current_node.val == current_node.next.val: + value_to_remove = current_node.val + while current_node and current_node.val == value_to_remove: + current_node = current_node.next + continue + last_unique_node.next = current_node + last_unique_node = current_node + current_node = current_node.next + last_unique_node.next = None + return sentinel.next +``` + +上を少し変えてwhileを抜けた後にlast_unique_node.next = Noneをしなくて良いようにした版。上の方がwhileループの中のlast_unique_nodeの更新場所が散らばらないので好み。 +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + sentinel = ListNode() + sentinel.next = head + last_unique_node = sentinel + current_node = head + while current_node: + if current_node.next and current_node.val == current_node.next.val: + value_to_remove = current_node.val + while current_node and current_node.val == value_to_remove: + current_node = current_node.next + last_unique_node.next = current_node + continue + last_unique_node = last_unique_node.next + current_node = current_node.next + return sentinel.next +``` + +重複を発見したら申し送る。1重ループ。 +こっちの方が個人的には好みかも。処理が追いやすい気がする。 + +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + sentinel = ListNode() + last_unique_node = sentinel + current_node = head + value_to_remove = None + while current_node: + if current_node.val == value_to_remove: + current_node = current_node.next + continue + if current_node.next and current_node.val == current_node.next.val: + value_to_remove = current_node.val + continue + last_unique_node.next = current_node + last_unique_node = last_unique_node.next + current_node = current_node.next + last_unique_node.next = None + return sentinel.next +``` + +3rd + +`if current_node.next and current_node.val == current_node.next.val:`のif文でcurrent_nodeも動かすかは迷った。「重複するノードを見つけました、あとはよろしく」というのは見つけたんだから処理もしてくれという気持ちにもなり少し気が利かないような気もするが、あくまでも重複を見つける担当として責務を明確にしておく方が読みやすい気もする。 +動かす場合は2つ一気に動かせるので`current_node = current_node.next.next`と書ける。 + + +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + sentinel = ListNode() + last_unique_node = sentinel + current_node = head + value_to_remove = None + while current_node: + if current_node.val == value_to_remove: + current_node = current_node.next + continue + if current_node.next and current_node.val == current_node.next.val: + value_to_remove = current_node.val + continue + last_unique_node.next = current_node + last_unique_node = last_unique_node.next + current_node = current_node.next + last_unique_node.next = None + return sentinel.next +``` From ca80aeda25b668fa01240bac291de9a9e37d0f71 Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Thu, 15 Feb 2024 00:14:57 +0900 Subject: [PATCH 2/6] Update 82. Remove Duplicates from Sorted List II.md --- 82. Remove Duplicates from Sorted List II.md | 99 ++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/82. Remove Duplicates from Sorted List II.md b/82. Remove Duplicates from Sorted List II.md index 85d8aba..50c3470 100644 --- a/82. Remove Duplicates from Sorted List II.md +++ b/82. Remove Duplicates from Sorted List II.md @@ -119,3 +119,102 @@ class Solution: last_unique_node.next = None return sentinel.next ``` + +↓追加(2024/02/15) + +4th +2重ループ。関数に切り出してみた。 + +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + def is_duplicated(node1, node2): + return node1 and node2 and node1.val == node2.val + + def skip_nodes(start, value_to_skip): + current = start + while current: + if current.val != value_to_skip: + break + current = current.next + return current + + sentinel = ListNode() + last_unique_node = sentinel + current = head + while current: + if is_duplicated(current, current.next): + current = skip_nodes(current, current.val) + last_unique_node.next = current + else: + last_unique_node.next = current + last_unique_node = last_unique_node.next + current = current.next + return sentinel.next +``` + +1重ループ。`need_remove` と`value_to_remove`の2変数を定義したが後者だけで十分な気がする。 + +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + def is_duplicated(node1, node2): + return node1 and node2 and node1.val == node2.val + + sentinel = ListNode() + last_unique_node = sentinel + current = head + need_remove = False + value_to_remove = None + while current: + if need_remove and current.val == value_to_remove: + pass + elif is_duplicated(current, current.next): + need_remove = True + value_to_remove = current.val + else: + need_remove = False + value_to_remove = None + last_unique_node.next = current + last_unique_node = last_unique_node.next + current = current.next + last_unique_node.next = None + return sentinel.next +``` + +再帰でも書いた。意外とシンプル。 +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + def delete_duplicates(node, value_to_remove): + if node is None: + return None + elif node.val == value_to_remove: + return delete_duplicates(node.next, value_to_remove) + elif node.next and node.val == node.next.val: + return delete_duplicates(node.next, node.val) + else: + node.next = delete_duplicates(node.next, None) + return node + return delete_duplicates(head, None) +``` + +5th +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + sentinel = ListNode() + prev = sentinel + current = head + while current: + if current.next and current.val == current.next.val: + value_to_remove = current.val + while current and current.val == value_to_remove: + current = current.next + prev.next = current + else: + prev.next = current + prev = prev.next + current = current.next + return sentinel.next +``` From d1a2dc9d66ec10d5f2ab84086400b3c4c5fff92a Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Fri, 1 Mar 2024 20:51:48 +0900 Subject: [PATCH 3/6] Update 82. Remove Duplicates from Sorted List II.md --- 82. Remove Duplicates from Sorted List II.md | 66 ++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/82. Remove Duplicates from Sorted List II.md b/82. Remove Duplicates from Sorted List II.md index 50c3470..6b2e1e9 100644 --- a/82. Remove Duplicates from Sorted List II.md +++ b/82. Remove Duplicates from Sorted List II.md @@ -218,3 +218,69 @@ class Solution: current = current.next return sentinel.next ``` + +6th +二重ループ。関数に切り出したほうが見通しが良い。 +whileの中のifをcontinueにするかif-elseにするのかは好みか。 + +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + def skip_duplicated_nodes(node, value_to_remove): + while node and node.val == value_to_remove: + node = node.next + return node + + sentinel = ListNode() + current = head + prev = sentinel + while current: + if current.next and current.val == current.next.val: + current = skip_duplicated_nodes(current.next, current.val) + prev.next = current + continue + prev.next = current + prev = prev.next + current = current.next + return sentinel.next +``` + +1重ループ。うーん。if, elifの`prev.next = current`をwhileの外で`prev.next = None`にするようにすれば`current = current.next`を共通部分として括れるけど。 +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + sentinel = ListNode() + current = head + prev = sentinel + value_to_remove = None + while current: + if current.val == value_to_remove: + current = current.next + prev.next = current + elif current.next and current.val == current.next.val: + value_to_remove = current.val + current = current.next + prev.next = current + else: + prev.next = current + prev = prev.next + current = current.next + return sentinel.next +``` + +再帰 +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + def delete_duplicates(node, value_to_remove): + if node is None: + return None + if node.val == value_to_remove: + return delete_duplicates(node.next, value_to_remove) + if node.next and node.val == node.next.val: + return delete_duplicates(node.next, node.val) + node.next = delete_duplicates(node.next, None) + return node + + return delete_duplicates(head, None) +``` From d8394c10f293ac7703f73ee0e88f193bd533c323 Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Mon, 4 Mar 2024 12:50:36 +0900 Subject: [PATCH 4/6] Update 82. Remove Duplicates from Sorted List II.md --- 82. Remove Duplicates from Sorted List II.md | 38 ++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/82. Remove Duplicates from Sorted List II.md b/82. Remove Duplicates from Sorted List II.md index 6b2e1e9..6eccb32 100644 --- a/82. Remove Duplicates from Sorted List II.md +++ b/82. Remove Duplicates from Sorted List II.md @@ -27,6 +27,42 @@ class Solution: return sentinel.next ``` +> 全体的に腕力で解決している感覚を持っているからです。 +ワーキングメモリーをふんだんに使いながら書いている感じがします。 +一般に、コードを読むのは、ワーキングメモリーを使う行為です。 +変数の意味であったり、何が入っていて、どういう処理がなされて、その時点で、どういう値が入る可能性があって、この関数は、例外を投げる可能性があるんだっけないんだっけ。 +そういうことを考えながら頭の中で走らせています。だから、ワーキングメモリーをさっさと開放してあげることが大事です。 + +> while A: + if B: + C + continue + D +これ、たしかに、 +「B は気にしなくていいので C して次に行く、D が本体。」と読めるときはいいんですが、C が長いと、ワーキングメモリーを保持させた状態で、さらに複雑な思考を要求することになりますね。 +逆に、D が長いと、continue にしたほうが読みやすく、どちらも短いなら、どっちでもそんなに変わりません。 +今回、C に while が入っているので、continue がどのループへの continue か一瞬迷うという事情もあるように思います。 + +>while current_node: + if current_node.next and current_node.val == current_node.next.val: + current_node = skip_until_value_change(current_node) + continue + unique_nodes.append(current_node) + current_node = current_node.next +なので、ここを skip_until_value_change でくくると言いたいことが分かります。 +もう一つ、これは current_value のことを忘れてもいいのだということが分かるという意味もあります。 + +>これは趣味の範囲ですが、current_node は名前として長い感じがします。 +ここのループにおいては主役なんだから、主役に、他と区別するためではない形容詞がついているのは不自然なんです。 +while node: + if node.next and node.val == node.next.val: + node = skip_until_value_change(node) + continue + unique_nodes.append(node) + node = node.next +>「あなたもよっぽど分らないのね。だから天璋院様の御祐筆の妹の御嫁に行った先きの御っかさんの甥の娘なんだって、先っきっから言ってるんじゃありませんか」 +名前は、なんていうか、状況に応じた適切な呼び方があるわけです。長ければ可読性が高いわけじゃないです。 + 2nd 重複を発見したら変えるな。2重ループ。 @@ -49,6 +85,8 @@ class Solution: return sentinel.next ``` +> 2nd-1 の current_node は、last_unique_node との対比になっているので、いいかなとは思います。 + 上を少し変えてwhileを抜けた後にlast_unique_node.next = Noneをしなくて良いようにした版。上の方がwhileループの中のlast_unique_nodeの更新場所が散らばらないので好み。 ```python class Solution: From 13273e0e6eef0b6a837a31bb2a9f61dedb63eafd Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Sat, 11 May 2024 18:48:01 +0900 Subject: [PATCH 5/6] Update 82. Remove Duplicates from Sorted List II.md --- 82. Remove Duplicates from Sorted List II.md | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/82. Remove Duplicates from Sorted List II.md b/82. Remove Duplicates from Sorted List II.md index 6eccb32..3141f2d 100644 --- a/82. Remove Duplicates from Sorted List II.md +++ b/82. Remove Duplicates from Sorted List II.md @@ -322,3 +322,28 @@ class Solution: return delete_duplicates(head, None) ``` + +7th + +2重ループ +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + def skip_duplicates(node, value_to_skip): + while node and node.val == value_to_skip: + node = node.next + return node + + sentinel = ListNode() + prev = sentinel + current = head + while current: + if current.next and current.val == current.next.val: + current = skip_duplicates(current.next, current.val) + continue + prev.next = current + prev = prev.next + current = current.next + prev.next = None + return sentinel.next +``` From 143c6af395c0ecb2de90fadbd332068c99ee0ad9 Mon Sep 17 00:00:00 2001 From: Ayato Hayashi Date: Tue, 12 Nov 2024 19:14:52 +0900 Subject: [PATCH 6/6] Update 82. Remove Duplicates from Sorted List II.md --- 82. Remove Duplicates from Sorted List II.md | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/82. Remove Duplicates from Sorted List II.md b/82. Remove Duplicates from Sorted List II.md index 3141f2d..cf547e2 100644 --- a/82. Remove Duplicates from Sorted List II.md +++ b/82. Remove Duplicates from Sorted List II.md @@ -347,3 +347,29 @@ class Solution: prev.next = None return sentinel.next ``` + + +8th + +元のLinkedListを破壊せずに新しいLinkedListを作る解法で解いた。 + +```python +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + def skip_duplicates(node, val_to_skip): + while node and node.val == val_to_skip: + node = node.next + return node + + sentinel = ListNode() + prev_node_of_new_list = sentinel + node = head + while node: + if node.next and node.val == node.next.val: + node = skip_duplicates(node.next, node.val) + continue + prev_node_of_new_list.next = ListNode(val=node.val) + prev_node_of_new_list = prev_node_of_new_list.next + node = node.next + return sentinel.next +```