From 31dafab6aa001f9fa49e18e4b5cb790c6e104c50 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: Sat, 2 May 2026 12:48:29 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20set=EC=9D=84=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=9C=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- linked-list-cycle/gyeo-ri.py | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 linked-list-cycle/gyeo-ri.py diff --git a/linked-list-cycle/gyeo-ri.py b/linked-list-cycle/gyeo-ri.py new file mode 100644 index 0000000000..15b5052051 --- /dev/null +++ b/linked-list-cycle/gyeo-ri.py @@ -0,0 +1,52 @@ +# Definition for singly-linked list. +class ListNode: + def __init__(self, val=0, next=None): + self.val: int = val + self.next: ListNode | None = next + + +class Solution: + def hasCycle(self, head: ListNode | None) -> bool: + visited_nodes = set() + while head is not None: + if head in visited_nodes: + return True + + visited_nodes.add(head) + head = head.next + return False + + +if __name__ == "__main__": + test_cases = [ + ([3, 2, 0, -4], 1, True), + ([1, 2], 0, True), + ([1], -1, False), + ([], -1, False), + ] + + solution = Solution() + + for idx, (inp, pos, expected) in enumerate(test_cases, start=1): + head = None + nodes = [] + + for value in reversed(inp): + head = ListNode(value, head) + + curr = head + + while curr: + nodes.append(curr) + curr = curr.next + + if pos != -1 and nodes: + nodes[-1].next = nodes[pos] + + result = solution.hasCycle(head) + + assert ( + result == expected + ), f"Test Case {idx} Failed: Expected {expected}, Got {result}" + + print("All test cases passed.") From f4b279589e415afdc2838e7aaeb8c3351c84f16b Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: Sat, 2 May 2026 13:34:15 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=ED=8F=AC=EC=9D=B8=ED=84=B0=20?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=EC=9D=98=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- linked-list-cycle/gyeo-ri.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/linked-list-cycle/gyeo-ri.py b/linked-list-cycle/gyeo-ri.py index 15b5052051..3dc2a4fcf1 100644 --- a/linked-list-cycle/gyeo-ri.py +++ b/linked-list-cycle/gyeo-ri.py @@ -1,3 +1,14 @@ +""" +[결과 요약] +# 시도한 로직 수: 2 + 1. Set을 사용하여 이전 노드를 저장하기(O(n) / O(n)) + - 메모리를 많이 사용함 + 2. 포인터를 사용하여 메모리 사용량 줄이기(O(n) / O(1) + - set 방식과 시간 복잡도(O(n))은 동일하나, 실제 성능은 개선됨 + - set은 이전 노드 비교를 위해 해시 탐색이 필요하여 상대적으로 성능 저하 +""" + + # Definition for singly-linked list. class ListNode: def __init__(self, val=0, next=None): @@ -7,13 +18,18 @@ def __init__(self, val=0, next=None): class Solution: def hasCycle(self, head: ListNode | None) -> bool: - visited_nodes = set() - while head is not None: - if head in visited_nodes: + node_1_step, node_2_steps = head, head + + # 1. 2 steps를 더 이상 탐색할 수 없을 때까지(node is None or node.next is None) 반복 + while node_2_steps is not None and node_2_steps.next is not None: + node_1_step = node_1_step.next + node_2_steps = node_2_steps.next.next + + # 2. 계속 돌렸을 때 node 1과 node 2가 만나면 순회가 있는 것 + # 일치 비교이므로 is 사용 + if node_1_step is node_2_steps: return True - visited_nodes.add(head) - head = head.next return False @@ -22,6 +38,7 @@ def hasCycle(self, head: ListNode | None) -> bool: ([3, 2, 0, -4], 1, True), ([1, 2], 0, True), ([1], -1, False), + ([1, 2], -1, False), ([], -1, False), ]