LeetCode #88: Merge Sorted Array
β’ 530 words β’ 3 min β’ updated
LeetCode #88: Merge Sorted Array:
The original problem states:
Do not return anything, modify
nums1in-place instead.
Instead, I opted for allocating a new list.
Naive and elegant #
O((m + n) * log (m + n)). Total disregard for the fact the inputs are already
sorted1.
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
return sorted(nums1 + nums2)Optimal #
O(m + n). We can achieve a linear solution by iterating only once on each
element, keeping track of two pointers.
Storage: we can either start with an empty list and keep appending2 to it, or
preallocate m + n elements and simply populate them3.
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
p1 = p2 = 0
a = [None] * (m + n)
# OR a = []
while (p1 + p2) < (m + n):
pa = p1 + p2
if p2 >= n or (p1 < m and nums1[p1] < nums2[p2]):
a[pa] = nums1[p1]
# OR a.append(nums1[p1])
p1 += 1
else:
a[pa] = nums2[p2]
# OR a.append(nums2[p2])
p2 += 1
return aOriginal: Naive and elegant #
The original problem modifies num1 in-place.
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
nums1[m:] = nums2
nums1.sort()Original: Optimal #
On top of the previous solution, just amend the end:
for i, el in enumerate(a):
nums1[i] = elOr, use list slicing:
nums1[:] = aNote that a simple assignment (nums1 = a or nums1 = a.copy()) does not
entail in-place modification.
A solution from scratch, without allocating a separate list, could look like this:
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
p1 = p2 = 0
while p1 < m:
if p2 >= n or nums1[p1] < nums2[p2]:
p1 += 1
else:
nums1[p1], nums2[p2] = nums2[p2], nums1[p1]
p1 += 1
def mysorted(v):
for i in range(len(v) - 1):
if v[i] > v[i+1]:
v[i], v[i+1] = v[i+1], v[i]
return v
nums1[m:] = mysorted(nums2.copy())Except that it fails for the following input:
nums1: [4,5,6,0,0,0]
m = 3
nums2: [1,2,3]
n = 3
result: [1,4,5,2,3,6]A revised solution β starts from the end, to account for the fact we need to modify the list in-place:
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
p1 = m - 1
p2 = n - 1
while p1 >= 0 and p2 >= 0:
if nums1[p1] < nums2[p2]:
nums1[p1 + p2 + 1] = nums2[p2]
p2 -= 1
else:
nums1[p1 + p2 + 1] = nums1[p1]
p1 -= 1
# This is a no-op
# while p1 >= 0:
# nums1[p1 + p2 + 1] = nums1[p1]
# p1 -= 1
while p2 >= 0:
nums1[p1 + p2 + 1] = nums2[p2]
p2 -= 1
# OR:
# nums1[:p2 + 1] = nums2[:p2 + 1]