Example 1
ready- Input
nums1 = [ 1, 2, 3 ] nums2 = [ 2, 5, 6 ]- Expected
[ 1, 2, 2, 3, 5, 6 ]- Why
- the two 2s are both kept while the lists interleave
Two teams have already sorted their score lists. Your job isn't to sort them again; it's to weave them into one correctly ordered leaderboard.
Given integer arrays nums1 and nums2, each sorted in non-decreasing
order, meaning each value is at least the value before it, return one sorted array
containing every value from both inputs.
Both inputs contain only their real values. nums1 has no padded placeholder slots.
The returned array has length nums1.length + nums2.length.
A useful way to picture the merge is from the back: compare the largest unused value in each input, write the larger one into the last open result slot, then move that input's pointer left.
0 <= nums1.length, nums2.length <= 100_0001 <= nums1.length + nums2.length-1_000_000_000 <= nums1[i], nums2[i] <= 1_000_000_000Hints
Concatenate the arrays and sort the result. It works, but it throws away the ordering work both inputs have already done.
Place one pointer at the end of each input and one at the end of the result. The larger pointed-to value must be the largest value still unwritten.
If either pointer moves before index 0, copy the remaining prefix from the other
array. Those values are already in the order the open result slots need.
Why does filling from the back avoid overwriting unread values when the destination is a preallocated buffer?
Visible cases
nums1 = [
1,
2,
3
]
nums2 = [
2,
5,
6
][
1,
2,
2,
3,
5,
6
]nums1 = []
nums2 = [
-4,
-1,
3
][
-4,
-1,
3
]nums1 = [
-2,
0,
7
]
nums2 = [][
-2,
0,
7
]Interview signal
The baseline ignores the inputs' sorted structure: join both arrays, then ask a general-purpose sort to order everything.
def merge(nums1: list[int], nums2: list[int]) -> list[int]:
return sorted(nums1 + nums2)It's compact and correct, but sorting makes comparisons that a true merge doesn't need.
Time O((m+n) log(m+n)) for m and n input values. Space O(m+n) for the returned array and the sorting work.
Allocate the result once. Put i on the last value of nums1, j on the last
value of nums2, and write on the result's last slot.
The larger of nums1[i] and nums2[j] is the largest value not yet written, so
it belongs at result[write]. Move that source pointer and write left, then
repeat. If one input runs out, the condition naturally takes values from the other.
def merge(nums1: list[int], nums2: list[int]) -> list[int]:
merged = [0] * (len(nums1) + len(nums2))
i = len(nums1) - 1
j = len(nums2) - 1
write = len(merged) - 1
while write >= 0:
if j < 0 or (i >= 0 and nums1[i] > nums2[j]):
merged[write] = nums1[i]
i -= 1
else:
merged[write] = nums2[j]
j -= 1
write -= 1
return mergedEvery comparison permanently places one value, so no work is repeated.
Time O(m+n) — every input value is written exactly once. Space O(m+n) for the required returned array, with O(1) extra space beyond that output.
LeetCode's version gives nums1 length m + n with trailing zero slots, mutates it in place, and returns void; ours receives only the real values and returns a new merged array.
Ready to run.
3 cases are queued.
Visible testcase
Case 1
Expected
[ 1, 2, 2, 3, 5, 6 ]