We have two linked lists, each already sorted in non-decreasing order, and we need to combine them into a single sorted linked list. The key phrase is "splicing together the nodes," which means we should reuse the existing nodes rather than creating new ones.
This is the same process as merging two sorted piles of cards by hand: look at the top card of each pile, take the smaller one, place it on the output pile, and repeat. When one pile runs out, move the remaining pile directly onto the output. The difference here is that we work with linked list pointers instead of arrays, so we have to rewire .next pointers as we go rather than copy values into a new array.
0 <= number of nodes <= 50 → Either or both lists can be empty, so the code must handle a null head without crashing.-100 <= Node.val <= 100 → Values can be negative. The comparison logic is identical for negative and positive values, and all values fit in a 32-bit integer with no overflow risk.Both lists are sorted in non-decreasing order → This is the property that makes a single linear pass possible. The smallest unmerged element across both lists is always one of the two current heads, so comparing the heads is enough to decide what comes next.At each step, we compare the heads of the two lists. The smaller head becomes the head of the merged result, and its .next points to the result of merging the rest of that list with the other list. That subproblem has the same shape as the original, with one fewer node, which makes recursion a direct fit.
The base cases are the empty lists. If one list is empty, the answer is the other list unchanged. If both are empty, returning either one returns null.
The recursion depth equals the total number of nodes, so this uses O(n + m) stack space. That becomes a problem for long lists, which the next approach avoids.
list1 is null, return list2. If list2 is null, return list1.list1 and list2.list1.val <= list2.val, set list1.next to the result of merging list1.next with list2. Return list1.list2.next to the result of merging list1 with list2.next. Return list2.The next approach performs the same merge iteratively, using a fixed number of pointers instead of the call stack, which brings the space down to O(1).
The comparison logic matches the recursive approach: compare heads, take the smaller one, advance that pointer. Instead of relying on the call stack to remember position, we keep a tail pointer at the end of the merged list we are building and append each chosen node there.
The first node of the merged list has no predecessor to attach to, which would otherwise force a special case before the loop. Allocating a dummy node up front removes that case. Every real node, including the first, is attached as tail.next, and the merged list begins at dummy.next.
The loop maintains an invariant: everything already attached after the dummy is sorted, and every value still in list1 or list2 is greater than or equal to the last attached value. This holds because both inputs are sorted and we always attach the smaller of the two heads. When the loop exits, one list is empty and the other holds only values at least as large as the last attached node, already in sorted order, so attaching it whole keeps the result sorted.
tail pointer to the dummy.list1 and list2 are non-null:list1.val and list2.val.tail.next, then advance that list's pointer.tail to tail.next.tail.next.dummy.next (the real head of the merged list).