This problem involves inserting a node with a given value (insertVal
) into a sorted circular linked list. The challenge lies in maintaining the sorted order and circular nature of the list, even when the list is empty or the insertion point isn't immediately obvious (e.g., when the value is smaller than the smallest or larger than the largest element due to the circular nature).
The solution efficiently handles all scenarios:
Empty List: If the head is null (empty list), a new node is created, its next
pointer points to itself (forming the circular list), and this node is returned as the new head.
Non-Empty List: The algorithm iterates through the list, comparing the current node's value (curr.val
) and the previous node's value (prev.val
) with the insertVal
. The insertion point is found when one of the following conditions is met:
prev.val <= insertVal <= curr.val
: The insertVal
fits between the prev
and curr
nodes.prev.val > curr.val && (insertVal >= prev.val || insertVal <= curr.val)
: This condition handles the circularity. If the prev
node's value is greater than the curr
node's value (meaning we've wrapped around), then insertVal
should be inserted either after prev
or before curr
.Insertion: Once the correct insertion point (prev
and curr
) is found, the new node is inserted: prev.next
points to the new node, and the new node's next
points to curr
.
Return Value: The original head is returned. This is important because the head might not be the smallest node in the list, and the insertion might not change which node is the head.
The Python code directly implements the approach described above:
class Solution:
def insert(self, head: 'Optional[Node]', insertVal: int) -> 'Node':
node = Node(insertVal) # Create new node
if head is None: # Handle empty list
node.next = node
return node
prev, curr = head, head.next # Initialize pointers
while curr != head: # Iterate until we've traversed the whole list
if prev.val <= insertVal <= curr.val or (prev.val > curr.val and (insertVal >= prev.val or insertVal <= curr.val)): #check for correct position
break # Exit loop once the right place is found
prev, curr = curr, curr.next # Move pointers
prev.next = node # Insert the node
node.next = curr
return head # Return the original head
The other languages (Java, C++, Go) follow a very similar structure, adapting the syntax to their respective language features. The core logic remains the same.
Time Complexity: O(N), where N is the number of nodes in the list. In the worst case, the algorithm needs to traverse the entire list to find the correct insertion point.
Space Complexity: O(1). The algorithm uses a constant amount of extra space, regardless of the list's size. We create one new node, but that's independent of the list size.