[Medium] 1669. Merge In Between Linked Lists
You are given two linked lists: list1 and list2 of sizes n and m respectively. Remove list1’s nodes from the a-th node to the b-th node (0-indexed), and put list2 in their place.
Examples
Example 1:
Input: list1 = [10,1,13,6,9,5], a = 3, b = 4, list2 = [1000000,1000001,1000002]
Output: [10,1,13,1000000,1000001,1000002,5]
list1: 10 → 1 → 13 → [6 → 9] → 5
↑ remove ↑
list2: 1000000 → 1000001 → 1000002
Result: 10 → 1 → 13 → 1000000 → 1000001 → 1000002 → 5
Example 2:
Input: list1 = [0,1,2,3,4,5,6], a = 2, b = 5, list2 = [1000000,1000001,1000002,1000003,1000004]
Output: [0,1,1000000,1000001,1000002,1000003,1000004,6]
Constraints
3 <= list1.length <= 10^41 <= a <= b < list1.length - 11 <= list2.length <= 10^4
The constraints guarantee a >= 1 and b < n - 1, so there is always at least one node before a and one node after b.
Thinking Process
What Do We Need?
We’re splicing list2 into list1 by removing positions a..b. That means three pointer rewirings:
prevA → list2_head → ... → list2_tail → afterB
We need:
prevA– the node at indexa - 1(just before the removed segment)afterB– the node at indexb + 1(just after the removed segment)tail2– the last node oflist2
Why No Dummy Node Needed?
Since a >= 1, the head of list1 is never removed, so we don’t need a dummy node to protect the head.
Walk-through
list1: 10 → 1 → 13 → 6 → 9 → 5 a=3, b=4
index: 0 1 2 3 4 5
Step 1: Walk to index a-1 = 2
prevA = node(13)
Step 2: From prevA, walk (b - a + 1) more steps to reach node at index b
then afterB = that node's next
afterB = node(5)
Step 3: Find tail of list2
list2: 1000000 → 1000001 → 1000002
tail2 = node(1000002)
Step 4: Rewire
prevA.next = list2 → 13 → 1000000
tail2.next = afterB → 1000002 → 5
Result: 10 → 1 → 13 → 1000000 → 1000001 → 1000002 → 5 ✓
Common Approaches
Typical techniques for this pattern:
| Approach | Time | Space | Notes |
|---|---|---|---|
| Iterative pointer walk (this problem) | O(n) | O(1) | Traversal, insertion |
| Dummy head node | O(n) | O(1) | Simplify head-edge cases |
| Reversal (3-pointer) | O(n) | O(1) | Reverse sublist or full list |
| Slow/fast pointers | O(n) | O(1) | Middle, cycle, merge lists |
Solution
from typing import Optional
# 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":
dummy = ListNode(0, list1)
prevA = dummy
# Find node before index a.
for _ in range(a):
prevA = prevA.next
# Move to node at index b, then step once more to index b+1.
afterB = prevA
for _ in range(b - a + 1):
afterB = afterB.next
afterB = afterB.next
# Attach list2 at cut position.
prevA.next = list2
# Find tail of list2.
tail = list2
while tail.next:
tail = tail.next
# Connect tail of list2 to remainder of list1.
tail.next = afterB
return dummy.next
Solution Explanation
Approach: Iterative pointer walk (this problem)
Key idea: ### What Do We Need?
How the code works:
prevA– the node at indexa - 1(just before the removed segment)afterB– the node at indexb + 1(just after the removed segment)tail2– the last node oflist2
Walkthrough — input list1 = [10,1,13,6,9,5], a = 3, b = 4, list2 = [1000000,1000001,1000002], expected output [10,1,13,1000000,1000001,1000002,5]:
- Initialize variables from the problem setup.
- Apply the main loop / recursion until the condition is met.
- Confirm the result matches the expected output.
Time: O(n + m) – traverse list1 up to index b, then traverse all of list2 · Space: O(1) – only pointer variables## Key Details
Without Dummy (Slightly Simpler)
Since the constraints guarantee a >= 1, we can skip the dummy:
class Solution:
def mergeInBetween(
self, list1: "ListNode", a: int, b: int, list2: "ListNode"
) -> "ListNode":
prevA = list1
for _ in range(a - 1):
prevA = prevA.next
afterB = prevA
for _ in range(b - a + 1):
afterB = afterB.next
prevA.next = list2
tail = list2
while tail.next:
tail = tail.next
tail.next = afterB
return list1
Common Mistakes
- Off-by-one on
prevA: Walkingasteps from head lands on indexa, but we need indexa - 1. Use a dummy or walka - 1steps. - Off-by-one on
afterB: Forgetting the final.nextafter reaching the node at indexb. - Forgetting to find
tail2: The connectionlist2_tail → afterBis easy to miss if you only setprevA → list2.
Key Takeaways
- “Splice list into list” = find the boundary pointers (
prevA,afterB) + find the tail of the inserted list + three pointer rewirings - When the head can never be removed, a dummy node is optional but can simplify uniform traversal
- Constraints like
a >= 1andb < n - 1eliminate edge cases – always read them carefully
Related Problems
- 206. Reverse Linked List – basic pointer manipulation
- 25. Reverse Nodes in k-Group – segment-based list surgery
- 86. Partition List – pointer rewiring with dummy nodes
- 143. Reorder List – find middle, reverse, merge
References
- LC 1669: Merge In Between Linked Lists on LeetCode
- LeetCode Discuss — LC 1669: Merge In Between Linked Lists
- LeetCode Editorial (may require premium)