diff --git a/83. Remove Duplicates from Sorted List.md b/83. Remove Duplicates from Sorted List.md new file mode 100644 index 0000000..5653473 --- /dev/null +++ b/83. Remove Duplicates from Sorted List.md @@ -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 +``` +となっていて、「なんかする」部分だけやることの言語化をサボらなければ解けそう。 +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: + 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) +``` \ No newline at end of file