diff --git a/141.Linked_List_Cycle.md b/141.Linked_List_Cycle.md new file mode 100644 index 0000000..e6c14c6 --- /dev/null +++ b/141.Linked_List_Cycle.md @@ -0,0 +1,150 @@ +1st. +C++で解いた経験のある問題。fast, slowの二つのポインタを用意しheadからスタートする。 +fastがslowに追いついたときループがある。逆に追い付くことなくslowがnullptrまでいった場合ループはないと言える。 +というのが基本的な方針として重いついたのでその方針で実装してみる。 + +基本的にはこれでいけていると思う(フロイドの循環検出法というよう) +しかし、入力が[]のときやノードが一つのときも確認出来ているかが少し分かりにくい? +また、setで探索したノードを保持して以前探索していた場合はTrueという方針がある。 +こちらの方が直感敵だし、間違えなさそうではある。しかし、setで保持するぶんメモリを使う? + +```Python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + + fast = head + slow = head + + while fast and fast.next: + + fast = fast.next.next + slow = slow.next + + if fast == slow: + return True + + return False +``` + +```Python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + visited = set() + + current_node = head + while current_node: + if current_node in visited: + return True + visited.add(current_node) + current_node = current_node.next + + return False +``` + +2nd. +current から nodeに変更した。 +visitedをseenにする案も見かけたが個人的にvisitedのほうが分かりやすい気がしたのでそのままにした。 +set()を使う方法は空間計算量はO(n):nは要素数であるがかなり分かりやすく書きやすい。 + +```Python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + visited = set() + node = head + while node: + if node in visited: + return True + visited.add(node) + node = node.next + return False +``` + +```Python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + fast = head + slow = head + + while head and head.next: + head = head.next.next + slow = slow.next + + if head == slow: + return True + return False +``` + +3rd. +```Python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + visited = set() + node = head + while node: + if node in visited: + return True + visited.add(node) + node = node.next + return False +``` + +```Python +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + fast = head + slow = head + + while fast and fast.next: + fast = fast.next.next + slow = slow.next + if fast == slow: + return True + return False +``` + +tk-hirom さんのレポジトリより +https://github.com/tk-hirom/Arai60/pull/1/commits/967ba6e39e0f6fd44a044778596f7dcd13ad0160 +setを使った実装ができるかをみているよう。 +ここでsetであることが大事でlistだと検索に時間計算量O(n)かかるが、setだとO(1)で検索できる。 +今回のように順序が関係ない場合setのほうがよい。 + +疑問:Pythonのlistとsetでは今回の場合使用するメモリの量はどちらが大きいのか + +予想:setのほうが重複するデータや順序の情報を持たないので小さい? +⇒こういったことはどのように調べたら良いのか