Skip to content

82. Remove Duplicates from Sorted List II#38

Open
skypenguins wants to merge 1 commit into
mainfrom
leetcode/arai60/problem-82
Open

82. Remove Duplicates from Sorted List II#38
skypenguins wants to merge 1 commit into
mainfrom
leetcode/arai60/problem-82

Conversation

@skypenguins

Copy link
Copy Markdown
Owner

82. Remove Duplicates from Sorted List II

次回予告: 98. Validate Binary Search Tree

@skypenguins skypenguins self-assigned this Jun 25, 2026
Comment thread memo.md
# 末尾節の古いnextを切る
unique_groups[-1][0].next = None

return unique_groups[0][0]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

こちらのコードは、入力を書き換えていることは認識しておくとよいです。
https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0#heading=h.gys2docabo9y

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

入力を書き換えないのであれば、例えば、以下のように書けます。

from collections import OrderedDict
class Solution:
    def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
        node = head
        value_to_count = OrderedDict()
        while node is not None:
            if node.val not in value_to_count:
                value_to_count[node.val] = 1
            else:
                value_to_count[node.val] += 1
            node = node.next

        dummy = ListNode()
        tail = dummy
        for value, count in value_to_count.items():
            if count == 1:
                tail.next = ListNode(value)
                tail = tail.next

        return dummy.next

(nodeを保持する代わりに何個あったかカウントするようにしました。新しいnodeをつくるときは、valueさえあればいいので)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

コード例の提示ありがとうございます。
この関数が使われる状況によりますが、入力を書き換えているかどうかは意識すべきですね

Comment thread memo.md
# 末尾節の古いnextを切る
unique_groups[-1][0].next = None

return unique_groups[0][0]

@h-masder h-masder Jun 26, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

元のコードについてですが、dummyを使うと、もう少しシンプルに書けそうです

        dummy = ListNode()
        tail = dummy

        for nodes in value_to_node.values():
            if len(nodes) == 1:
                tail.next = nodes[0]
                tail = tail.next

        tail.next = None

        return dummy.next

Comment thread memo.md
```py
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
value_to_node = defaultdict(list)

@h-masder h-masder Jun 26, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

一応ですが、Python2.7以降Pyhon3.7以前ならOrdereddictを使うと入れた順番を保持します。
https://pypi.org/project/ordereddict/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

さらに付け加えると、3.7 以降は通常の dict でもデフォルトで挿入順を保持するのが仕様として定められているので基本的には通常の dict を使うのが良いとされているようで、バージョンを意識しながら書けると良さそうです。

Since Python 3.7, dictionaries are ordered by default, so there is usually little need for these functions; prefer PyDict* where possible.

https://docs.python.org/ja/3/c-api/dict.html#ordered-dictionaries

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

3.7以降であれば基本的に通常のdictで良さそうですね

Comment thread memo.md
return dummy.next
```
- こちらは空間計算量: $O(1)$ で済む
- だいぶ前に(別の問題だが)似た解法を使ったのを思い出した

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

この方針ではソートされていることが前提ですが、元の方針ならソートされていなくてもできる、ということはおさえておきたいですね。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

おっしゃる通り、ソート前提でなく(重複文字列が連続していない)とも使えるような解法を考えていました。

Comment thread memo.md
Comment on lines +125 to +135
if current.next and current.val == current.next.val:
visited_value = current.val

while current and current.val == visited_value:
current = current.next

previous.next = current
continue

previous = current
current = current.next

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

if A:
    長い処理
    continue
短い処理

の形ですが、これだと「長い処理」を読んだあと「短い処理」の部分の条件を把握(思い出す)のに「長い処理」の前の A に遡って条件を確認しないといけなくて(あるいは、「not A の場合どうなるんだろう」、というのを頭に置いたまま「長い処理」を読むので長時間ワーキングメモリを取られる感じがして)個人的にはやや負荷を感じました。

if not A:
    短い処理
    continue
長い処理

のように入れ替えるとより読みやすいかもしれません。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

確かに初見だと、現在の分岐の書き方だとワーキングメモリを喰われますね。ご指摘ありがとうございます。

Comment thread memo.md
Comment on lines +121 to +122
previous = sentinel
current = head

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

previous, current という名前ですが、処理の途中で「previous は置き去りにしたまま current をどんどん進める」ところがあって個人的には少しギャップを感じました。

previous の代わりに unique_tail, saved_tail, tail_so_far などの説明的な名前でもいいのかなと思います。

current は current のままでもいいかもしれませんし、 checking とか単に node とかもいいかもしれません。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

自分だと tail_so_far がより適切だと感じました。ご指摘ありがとうございます。

Comment thread memo.md
```py
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
value_to_node = defaultdict(list)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

さらに付け加えると、3.7 以降は通常の dict でもデフォルトで挿入順を保持するのが仕様として定められているので基本的には通常の dict を使うのが良いとされているようで、バージョンを意識しながら書けると良さそうです。

Since Python 3.7, dictionaries are ordered by default, so there is usually little need for these functions; prefer PyDict* where possible.

https://docs.python.org/ja/3/c-api/dict.html#ordered-dictionaries

Comment thread memo.md
value_to_node = defaultdict(list)
node = head

while node:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

こちらのコメントをご参照ください。
ksaito0629/leetcode_arai60#1 (comment)

@skypenguins skypenguins Jun 28, 2026

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

コメントの参照ありがとうございます。今回の場合では node is not None の方がより安全だと理解しました。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants