We have a circular linked list where the nodes are sorted in ascending order, but the "start" of the list can be any node. Because it's circular, the last (largest) node points back to the first (smallest) node, creating a wrap-around point. We need to insert a new value while keeping the sorted order intact.
The complication is that the given head pointer might not be the smallest node, so we cannot assume we are starting from the beginning of the sorted sequence. We have to find the insertion point by examining the relationship between each pair of consecutive nodes.
There are three distinct cases to think about:
0 <= number of nodes <= 5 * 10^4 → The list can be empty, which is a special case we must handle. With up to 50,000 nodes, we need an O(n) or better approach.-10^6 <= Node.val, insertVal <= 10^6 → Values can be negative. Don't assume positive-only values.First understand the structure of the list, then decide where to insert.
In the first pass, we walk around the circular list to find the boundary where the largest node connects back to the smallest node. This is the single point where prev.val > curr.val. Once we know the boundary, we know both the maximum value (the node before the boundary) and the minimum value (the node after it), which fixes the sorted order of the whole list.
The second pass decides where insertVal belongs:
insertVal is greater than or equal to the max or less than or equal to the min, it is a new extreme value and belongs at the boundary.prev.val <= insertVal <= curr.val.This separates the two concerns cleanly at the cost of traversing the list twice.
head is null, create a new node that points to itself and return it.prev.val > curr.val). Track the node with the maximum value.insertVal >= max value or insertVal <= min value, insert at the boundary.prev.val <= insertVal <= curr.val.prev and curr.head.Loading animation...
This approach traverses the list twice. The next approach checks all three insertion conditions at every node, which finds the insertion point in a single pass.
Instead of first finding the boundary and then finding the insertion point, we can do everything in one traversal. We walk the list with two pointers (prev and curr) and check at each step whether this is the right place to insert.
There are three conditions, and we insert as soon as any of them is satisfied:
prev.val <= insertVal <= curr.val. The new value fits between these two consecutive nodes.prev.val > curr.val), and insertVal is either greater than or equal to prev.val (larger than the max) or less than or equal to curr.val (smaller than the min).The three conditions are exhaustive. A circular sorted list with distinct values has exactly one boundary where prev.val > curr.val. Every other adjacent pair has prev.val <= curr.val, so any value that is not a new extreme falls inside one such pair and Case 1 finds it. A value that is larger than the maximum or smaller than the minimum is a new extreme and belongs at the boundary, which Case 2 detects through prev.val > curr.val. The only way both checks fail for a full lap is when every node holds the same value, so no boundary exists; Case 3 then inserts at the starting position, which keeps the list sorted because all values are equal.
head is null, create a new node pointing to itself and return it.prev = head and curr = head.next.prev.val <= insertVal <= curr.val (normal insertion).prev.val > curr.val (we're at the boundary) AND (insertVal >= prev.val OR insertVal <= curr.val).prev and curr and return.prev and curr (any position works).head.Loading animation...
prev and curr) plus the new node.