-
Notifications
You must be signed in to change notification settings - Fork 0
82 remove duplicates from sorted list ii #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
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,44 @@ | ||
| # 82. Remove Duplicates from Sorted List II | ||
|
|
||
| <https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/> | ||
|
|
||
| ## step1(まず通す) | ||
|
|
||
| 「次とその次を見て、値が重複していたらその値を覚えておき、ちがう値が出てくるまで次を繋ぎ替え続ける。重複してなかったら一つ進む」という考え方。スタートから重複する可能性もあるのでhead の前にダミーヘッドを用意してheadから重複判定を開始する必要がある。ダミーヘッドは本当の head と値が重複しないように `-100 <= Node.val <= 100` の外である必要がある。 | ||
|
|
||
| ## step2(整形&他の人のコードを読む) | ||
|
|
||
| `does_duplicate_start` は条件分岐があってかつ return が False, True, False と並ぶのは認知不可高そう。`is None` だと長くなるが、単に `node` とか書けば短いので True になる条件一つ vs. その他は False の方がいいかも。 | ||
|
|
||
| 本体の方で、while のあとに if が来て処理が長い→else は短い処理なので、if の判定を入れ替えた方がいいかも。↑のコメントも T と F が入れ替わる形で。 | ||
|
|
||
| 変数名に略語を使うかどうかは流派によるだろうが、今回は関数名にも duplicate があるのでdup_val でもわかりそうと思いつつ、エディタが補完してくれるので略さずに書けというのもわかる。 | ||
|
|
||
| いつ仕様が変わるかわからないのでマジックナンバー避けるべしというのも納得: <https://github.com/goto-untrapped/Arai60/pull/43#discussion_r1695376875> | ||
|
|
||
| if else で書くか if の中で continue して else の方は外で書くかだが、今回はネストが深くない方がいいので continue かな。 | ||
|
|
||
| と思ったが、そもそも is_unique を関数化する意味が薄い気がして来た。関数の中身が一つの if else だけなので。そうなると、条件に否定がない方が見やすいと思うので結局元と同じ順番に戻った。 | ||
|
|
||
| -1000 がマジックナンバーになっておりよくないので、 float("-inf") にしてみた。マイナスなのは、一応ソートされてて欲しいので。一応 int vs. float の型の違いはあるが int の最大みたいなのはないので一旦これで。 | ||
|
|
||
| ## step3(10分以内にさっとかける * 3回) | ||
|
|
||
| node.next が None ならその先を見る意味もないので↓でもいいかもしれない。 | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
| dummy_head = ListNode(val=float("-inf"), next=head) | ||
| node = dummy_head | ||
| while node.next: | ||
| if node.next.next and node.next.val == node.next.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. ここの比較でheadとダミーヘッドとの値の比較は行われていないので、今回ダミーヘッドの値は考慮しなくても良いかと思いました
valに-infが入っているとなにかしらに使われるのかなと思って読むので、dummy_headは以下のようにしてもよいかと思いましたが、特に今のままでも弊害はないはずです。好みかと思います。
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. 確かにそうですね、初めに書いたコードでは dummy_head から比較していたのを head からの比較に変えた時にそこまで意識が回っていませんでした。
特殊な値を使う時は意図を持って(= 不要なら無闇に使わない)というのは一つの指針になりそうです。 ありがとうございます。 |
||
| duplicate_value = node.next.val | ||
| while node.next and node.next.val == duplicate_value: | ||
| node.next = node.next.next | ||
| else: | ||
| node = node.next | ||
|
|
||
| return dummy_head.next | ||
|
|
||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| from typing import Optional | ||
|
|
||
|
|
||
| # Definition for singly-linked list. | ||
| class ListNode: | ||
| def __init__(self, val=0, next=None): | ||
| self.val = val | ||
| self.next = next | ||
|
|
||
|
|
||
| class Solution: | ||
| def does_duplicate_start(self, node: Optional[ListNode]) -> bool: | ||
| if node is None or node.next is None: | ||
| return False | ||
| if node.val == node.next.val: | ||
| return True | ||
| return False | ||
|
|
||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
| dummy_head = ListNode(val=-1000, next=head) | ||
| node = dummy_head | ||
| while node is not None: | ||
| if self.does_duplicate_start(node.next): | ||
| dup_val = node.next.val | ||
| while node.next and node.next.val == dup_val: | ||
| node.next = node.next.next | ||
| else: | ||
| node = node.next | ||
|
|
||
| return dummy_head.next |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| from typing import Optional | ||
|
|
||
|
|
||
| # Definition for singly-linked list. | ||
| class ListNode: | ||
| def __init__(self, val=0, next=None): | ||
| self.val = val | ||
| self.next = next | ||
|
|
||
|
|
||
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
| dummy_head = ListNode(val=float("-inf"), next=head) | ||
| node = dummy_head | ||
| while node: | ||
| if node.next and node.next.next and node.next.val == node.next.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. step1 のように こちらのコメントをご参照ください。
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. ありがとうございます。 |
||
| duplicate_value = node.next.val | ||
| while node.next and node.next.val == duplicate_value: | ||
| node.next = node.next.next | ||
| else: | ||
| node = node.next | ||
|
|
||
| return dummy_head.next | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| from typing import Optional | ||
|
|
||
|
|
||
| # Definition for singly-linked list. | ||
| class ListNode: | ||
| def __init__(self, val=0, next=None): | ||
| self.val = val | ||
| self.next = next | ||
|
|
||
|
|
||
| class Solution: | ||
| def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: | ||
| dummy_head = ListNode(val=float("-inf"), next=head) | ||
| node = dummy_head | ||
| while node: | ||
| if node.next and node.next.next and node.next.val == node.next.next.val: | ||
| duplicate_value = node.next.val | ||
| while node.next and node.next.val == duplicate_value: | ||
| node.next = node.next.next | ||
| else: | ||
| node = node.next | ||
|
|
||
| return dummy_head.next |
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.
ある程度の規模の組織になると、ソースコードを書く量より読む量のほうが増えます。このとき、書くより読むのにかかるコストを下げたほうが、全体としてのコストが低くなります。読むにあたり、略語が使われていると、認知負荷が上がる場合があります。これを避けるため、フルスペルで書いたほうが良いのだと思います。
Coding Agent にコードを読み書きさせる場合はよく分からないです。フルスペルのほうが略語より、 Coding Agent がより正確に意味を読み取ってくれる気がするのですが、気のせいかもしれません。
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.
ありがとうございます。
そのお話聞いて、略語で書いても認知不可が上がらないかどうかは判断も難しいですしいちいちそれを気にするくらいなら常にフルスペルで書いた方が書く時の負担も軽いかもしれないなとも思いました。