1669. Merge in Between Linked Lists - Explanation
Description
Replace the nodes at indices a through b, inclusive, in list1 with all the nodes of list2. Indices start at 0. Connect the remaining prefix of list1 to list2, then connect the end of list2 to the remaining suffix of list1. Return the head of the combined list. Arrays in examples and test inputs show node values from head to tail.
Filled nodes in list1 are removed; list2 replaces them. The diagram below the arrow shows the resulting list.
Example 1:
Input: list1 = [2,4,6,8,10]
a = 1
b = 3
list2 = [7,9]
Output: [2,7,9,10]Explanation: Remove the nodes at indices 1, 2, and 3, which contain 4, 6, and 8. Inserting 7 -> 9 between the remaining nodes gives 2 -> 7 -> 9 -> 10.
Example 2:
Input: list1 = [1,2,3]
a = 1
b = 1
list2 = [5]
Output: [1,5,3]Explanation: Only the middle node, containing 2, is removed. Replace it with the single node containing 5 to get 1 -> 5 -> 3.
Example 3:
Input: list1 = [4,4,4,4]
a = 2
b = 2
list2 = [4,4]
Output: [4,4,4,4,4]Explanation: Remove one node and insert two nodes in its place. Although every value is 4, the resulting list has five nodes rather than four.
Constraints:
3 <= list1.length <= 100001 <= a <= b < list1.length - 11 <= list2.length <= 10000
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Linked Lists - Understanding singly linked list structure and node traversal
- Pointer Manipulation - Rewiring node connections by modifying next pointers
- Two Pointers - Tracking multiple positions in a linked list simultaneously
1. Convert To Array
Intuition
The problem asks us to remove nodes from index a to b in list1 and insert list2 in their place. By storing all nodes of list1 in an array, we gain direct access to any node by index. This makes it straightforward to connect the node just before position a to the head of list2, and then connect the tail of list2 to the node just after position b.
Algorithm
- Traverse
list1and store all nodes in an array. - Connect the node at index
a - 1to the head oflist2. - Traverse
list2to find its last node. - Connect the last node of
list2to the node at indexb + 1in the array. - Return the head of
list1.
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeInBetween(self, list1: ListNode, a: int, b: int, list2: ListNode) -> ListNode:
cur = list1
arr = []
while cur:
arr.append(cur)
cur = cur.next
arr[a - 1].next = list2
cur = list2
while cur.next:
cur = cur.next
cur.next = arr[b + 1]
return list1Time & Space Complexity
- Time complexity:
- Space complexity:
Where is the length of the first list and is the length of the second list.
2. Two Pointers
Intuition
Instead of using extra space to store all nodes, we can traverse list1 directly using pointers. We walk through the list, counting nodes until we reach position a - 1 (the node just before the removal range). We save this position, then continue until we pass position b to find the node that should come after list2. Finally, we rewire the pointers to splice list2 in place.
Algorithm
- Initialize a pointer
currat the head oflist1and a counteriat0. - Move
currforward untiliequalsa-1. Save this node ashead. - Continue moving
currforward untiliexceedsb. Nowcurrpoints to the node after the removed segment. - Set
head.nextto point tolist2. - Traverse
list2to find its tail node. - Set the tail of
list2to point tocurr. - Return the head of
list1.
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeInBetween(self, list1: ListNode, a: int, b: int, list2: ListNode) -> ListNode:
curr = list1
i = 0
while i < a - 1:
curr = curr.next
i += 1
head = curr
while i <= b:
curr = curr.next
i += 1
head.next = list2
while list2.next:
list2 = list2.next
list2.next = curr
return list1Time & Space Complexity
- Time complexity:
- Space complexity: extra space.
Where is the length of the first list and is the length of the second list.
3. Recursion
Intuition
We can solve this problem recursively by reducing the indices a and b as we move deeper into list1. When a reaches 1, we have found the insertion point and can attach list2. We then continue recursing with list2's tail to skip over the nodes that should be removed (while b counts down). When b reaches 0, we have passed all nodes to remove and can connect the tail of list2 to the remaining nodes of list1.
Algorithm
- If
a==1, we are at the insertion point:- Save
list1.nextasnxt. - Set
list1.next=list2. - Traverse to the end of
list2to find its tail. - Recursively call the function with
nxt,a=0,b-1, and the tail oflist2. - Return
list1.
- Save
- If
b==0, we have skipped all nodes to remove:- Set
list2.next=list1.nextto connect the tail oflist2to the rest oflist1. - Return
list1.
- Set
- Otherwise, recurse on
list1.nextwitha-1andb-1. - Return
list1.
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeInBetween(self, list1: ListNode, a: int, b: int, list2: ListNode) -> ListNode:
if a == 1 :
nxt = list1.next
list1.next = list2
while list2.next:
list2 = list2.next
self.mergeInBetween(nxt, 0, b - 1, list2)
return list1
if b == 0:
list2.next = list1.next
return list1
self.mergeInBetween(list1.next, a - 1, b - 1, list2)
return list1Time & Space Complexity
- Time complexity:
- Space complexity: for recursion stack.
Where is the length of the first list and is the length of the second list.
Common Pitfalls
Off-by-One Errors When Finding the Insertion Point
The node at index a - 1 should point to list2, and the tail of list2 should point to the node at index b + 1. Using index a or b directly results in incorrect splicing.
Forgetting to Find the Tail of list2
After connecting the node before position a to list2, you must traverse list2 to find its tail and connect it to the remaining nodes of list1. Skipping this step leaves the merged list incomplete.
Not Handling the Removed Nodes
The nodes from index a to b are no longer part of the result list. In languages without garbage collection, failing to properly handle these nodes can cause memory leaks.
Sign in to join the discussion