Given a node from a Circular Linked List which is sorted in ascending order, write a function to insert a value insertVal
into the list such that it remains a sorted circular list. The given node can be a reference to any single node in the list, and may not be necessarily the smallest value in the circular list.
If the list is empty (given node is null
), you should create a new single circular list and return the reference to that single node. Otherwise, you should return the original given node.
Example 1:
Input: head = [3,4,1], insertVal = 2 Output: [3,4,1,2] Explanation: In the figure above, there is a sorted circular list of three elements. You are given a reference to the node with value 3, and we need to insert 2 into the list. The new element should be inserted between node 1 and node 3. After the insertion, the list should look like this, and we should still return node 3.
Example 2:
Input: head = [], insertVal = 1 Output: [1] Explanation: The list is empty, so we need to create a single circular list and return the new node.
Example 3:
Input: head = [1,2,3], insertVal = 4 Output: [1,2,3,4]
Constraints:
0 <= Number of Nodes <= 5 * 104
-106 <= Node.val <= 106
-106 <= insertVal <= 106
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force method involves checking all possible insertion points within the circular sorted list to find the correct location for the new value. We essentially try every single position to see where the value fits according to the sorted order. This is like trying to fit a puzzle piece in every possible spot until you find the right one.
Here's how the algorithm would work step-by-step:
class Node:
def __init__(self, data=None):
self.data = data
self.next = None
def insert_into_sorted_circular_linked_list(head, insert_value):
new_node = Node(insert_value)
if not head:
new_node.next = new_node
return new_node
current_node = head
while True:
# Check if the new value fits between current and next node
if (current_node.data <= insert_value <= current_node.next.data) or \
(current_node.data > current_node.next.data and \
(insert_value >= current_node.data or insert_value <= current_node.next.data)):
new_node.next = current_node.next
current_node.next = new_node
return head
#Handles case where the list has a single repeating value
if current_node.data == current_node.next.data and current_node.next == head:
new_node.next = current_node.next
current_node.next = new_node
return head
current_node = current_node.next
# Traverse the list once to find the insertion point
if current_node == head:
#Insert at the end if value is the list max or min
new_node.next = current_node.next
current_node.next = new_node
return head
The goal is to find the correct spot to insert a new number into a sorted circle of numbers. We need to handle cases where the new number fits within the existing sorted order, and also cases where it should be the new minimum or maximum value in the circle.
Here's how the algorithm would work step-by-step:
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
def insert_into_sorted_circular_linked_list(head, insert_value):
new_node = Node(insert_value)
if not head:
new_node.next = new_node
return new_node
current_node = head
while True:
next_node = current_node.next
# Check if the new node belongs between current and next.
if (current_node.data <= insert_value <= next_node.data) or \
(current_node.data > next_node.data and \
(insert_value >= current_node.data or insert_value <= next_node.data)):
new_node.next = next_node
current_node.next = new_node
return head
current_node = next_node
# If we've traversed the entire list.
if current_node == head:
#Insert at the end if it's the new maximum.
new_node.next = next_node
current_node.next = new_node
return head
Case | How to Handle |
---|---|
Empty list (head is null) | Create a new circular linked list with the insertVal and return its head. |
List with only one node | Insert the new node after the existing node, making it a circular list. |
insertVal is smaller than the smallest value in the list | Insert the node before the smallest value (likely right after the largest value). |
insertVal is larger than the largest value in the list | Insert the node after the largest value (likely before the smallest value). |
insertVal falls between two existing values | Traverse the list and insert the node in the correct sorted position between the two values. |
All values in the list are the same and insertVal is equal to them | Insert the node after any existing node as the list is already sorted. |
All values in the list are the same and insertVal is different | Insert the node after any node, maintaining circularity. |
Very large list impacting performance | The solution should have linear time complexity O(n) as it might need to traverse the entire list in the worst case. |