1.描述:
给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。
初始化 A 和 B 的元素数量分别为 m 和 n。
示例:
输入:
A = [1,2,3,0,0,0], m = 3
B = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
2.理解
用python最直接的想法是将B并入到A后面,然后调用sort方法,一开始很怀疑不会通过,结果试了试,发现还真行…
当然,仅仅pass并不是目的。已知该题目中两个序列已经有序,我们可以设置两个指针,分别指向A和B开头,然后比较两个值,根据不同情况对指针进行后移。但是如果直接对A从前往后进行操作显然数据移位时浪费大量时间,而且依据题意,不能使用第三个序列 (这是我的思维误区,其实可以先添加一个序列,最后将结果赋给A就行…)
所以在之前猜想的基础上,我们可以将指针设置成从后往前,每次将最大的数放入A的最末端,此时最坏的时间复杂度为O(n+m)。
3.答题:
3.1简单的想法
class Solution(object):
def merge(self, A, m, B, n):
"""
:type A: List[int]
:type m: int
:type B: List[int]
:type n: int
:rtype: None Do not return anything, modify A in-place instead.
"""
for i in range(m,m+n):
A[i]=B[i-m]
A.sort()
执行时间24 ms,消耗内存11.8 MB。
3.2逆双向指针
class Solution(object):
def merge(self, A, m, B, n):
"""
:type A: List[int]
:type m: int
:type B: List[int]
:type n: int
:rtype: None Do not return anything, modify A in-place instead.
"""
p_a = m-1 # 指向A的有序数字末尾
p_b = n-1 # 指向B的有序数字末尾
p = m+n-1 # 指向A序列末尾
while p_a >= 0 and p_b >= 0: # 当a和b里面数据都未遍历完时
if A[p_a] > B[p_b]:
A[p] = A[p_a]
p -= 1
p_a -= 1
else:
A[p] = B[p_b]
p -= 1
p_b -= 1
while p_a < 0 and p_b >= 0: # 此时是a中的数据已经遍历完
A[p_b] = B[p_b]
p_b -= 1
执行时间20 ms,消耗内存11.7 MB。
3.3双向指针:利用指针从前往后
class Solution(object):
def merge(self, A, m, B, n):
"""
:type A: List[int]
:type m: int
:type B: List[int]
:type n: int
:rtype: None Do not return anything, modify A in-place instead.
"""
p_a = 0
p_b = 0
p = 0
result = (m+n)*[0]
while p_a < m and p_b < n:
if A[p_a] > B[p_b]:
result[p] = B[p_b]
p += 1
p_b += 1
else:
result[p] = A[p_a]
p += 1
p_a += 1
while p_a == m and p_b < n:
result[p] = B[p_b]
p += 1
p_b += 1
while p_a < m and p_b == n:
result[p] = A[p_a]
p += 1
p_a += 1
A[:] = result
其实后面两种方法原理类似。只不过我的写法有些憨憨…尚且有优化空间。
题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sorted-merge-lcci