1、来源:力扣(LeetCode)第88题:合并两个有序数组
解法1:双指针从前往后
对于有序数组可以通过双指针法达到O(n + m)的时间复杂度
最直接的算法实现时将指针p置为nums1的开头,p为nums2的开头,在每一步将最小值放入到输出数组中,由于nums1是用于输出的数组,需要将nums1中的前m个元素放在其他地方,也就需要O(m)的空间复杂度。
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: void Do not return anything, modify nums1 in-place instead.
"""
# Make a copy of nums1.
nums1_copy = nums1[:m]
nums1[:] = []
p,q = 0,0
# Compare elements from nums1_copy and nums2
# and add the smallest one into nums1.
while p < m and q < n :
if nums1_copy[p] < nums2[q]:
nums1.append(nums1_copy[p])
p += 1
else:
nums1.append(nums2[q])
q += 1
# if there are still elements to add
if p < m:
nums1[p + n:] = nums1_copy[p:]
if q < n:
nums1[q + m:] = nums2[q:]
解法2:双指针从后往前
解法1已经取得了最优的时间复杂度O(n + m),但需要使用额外空间。这是由于从头改变num1的元素时,需要把nums1的元素存放带其他位置。
如果我们从结尾开始改写nums1的值又如何呢?这里没有信息,因此不需要额外空间。
class Solution: def merge(self, nums1, m: int, nums2, n: int) -> None: """ Do not return anything, modify nums1 in-place instead. """ p,q,p1= m - 1,n - 1,m + n - 1 while p > -1 and q > -1: if nums1[p] < nums2[q]: nums1[p1] = nums2[q] q -= 1 p1 -= 1 else: nums1[p1] = nums1[p] p -= 1 p1 -= 1 nums1[:q + 1] = nums2[:q + 1]