Linked List Cycle
Clarify the problem:
- The problem requires determining whether a linked list contains a cycle.
- We need to identify if there is a cycle in the linked list and return a boolean value indicating the presence or absence of a cycle.
Analyze the problem:
- Input: The head node of a linked list.
- Output: A boolean value indicating whether there is a cycle in the linked list.
- Constraints:
- The linked list may be empty.
- The linked list may contain any number of nodes.
- The nodes in the linked list may have arbitrary values.
- The linked list may have a cycle, where a node points to a previously visited node, creating a loop.
Design an algorithm:
- We can use the Floyd's Tortoise and Hare algorithm to determine if there is a cycle in the linked list.
- The algorithm uses two pointers, one moving at a slower pace (tortoise) and the other at a faster pace (hare).
- If there is a cycle, the hare will eventually catch up to the tortoise, indicating the presence of a cycle.
- We can start with both pointers at the head of the linked list and move them accordingly.
- The hare pointer will move two steps at a time, while the tortoise pointer will move one step at a time.
- If the hare reaches the end of the linked list (i.e., a null node), there is no cycle.
- If the hare and tortoise meet at any point, there is a cycle in the linked list.
Explain your approach:
- We will implement a function called
hasCycle
that takes the head of a linked list as input and returns a boolean value indicating whether there is a cycle. - We will use two pointers,
tortoise
andhare
, initialized at the head of the linked list. - We will iterate through the linked list, moving the
tortoise
pointer one step at a time and thehare
pointer two steps at a time. - If the
hare
pointer reaches the end of the linked list (i.e., a null node), we will returnFalse
, indicating no cycle. - If the
hare
andtortoise
pointers meet at any point, we will returnTrue
, indicating the presence of a cycle.
- We will implement a function called
Write clean and readable code:
pythonclass ListNode: def __init__(self, x): self.val = x self.next = None def hasCycle(head): if not head or not head.next: return False tortoise = head hare = head.next while tortoise != hare: if not hare or not hare.next: return False tortoise = tortoise.next hare = hare.next.next return True
Test your code:
- To test the code, we can create a linked list with or without a cycle and call the
hasCycle
function on it. - Test case 1: No cycle
python- To test the code, we can create a linked list with or without a cycle and call the
- Test case 2: Cycle
# Linked list: 1 -> 2 -> 3 -> 4 -> 2 (points back to the second node) head = ListNode(1) head.next = ListNode(2) head.next.next = ListNode(3) head.next.next.next = ListNode(4) head.next.next.next.next = head.next print(hasCycle(head)) # Output: True
Optimize if necessary:
- The Floyd's Tortoise and Hare algorithm has an optimal time complexity of O(n) and a space complexity of O(1), where n is the number of nodes in the linked list.
- The algorithm detects the cycle efficiently by traversing the linked list using two pointers, without requiring any additional data structures.
Handle error cases:
- We handle the case when the linked list is empty by checking if the head node is
None
or if the head node has no next node. - In such cases, we return
False
to indicate no cycle.
- We handle the case when the linked list is empty by checking if the head node is
Discuss complexity analysis:
- Time complexity: The algorithm has a time complexity of O(n), where n is the number of nodes in the linked list. This is because both pointers traverse the linked list at different speeds, with the faster pointer covering the distance twice as fast as the slower pointer.
- Space complexity: The algorithm has a space complexity of O(1) as it uses only a constant amount of additional space to store the two pointers. It does not require any additional data structures proportional to the size of the input.
# Linked list: 1 -> 2 -> 3 -> 4 -> None
head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(3)
head.next.next.next = ListNode(4)
print(hasCycle(head)) # Output: False
python