一、88. 合并两个有序数组(双指针)
https://leetcode-cn.com/problems/merge-sorted-array/
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
法零:nums1[:] = sorted(nums1[:m] + nums2)
法一:双指针 / 从前往后,时间O(n+m),空间O(m)
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
"""
# Make a copy of nums1.
nums1_copy = nums1[:m]
nums1[:] = []
p1 = 0
p2 = 0
while p1 < m and p2 < n:
if nums1_copy[p1] < nums2[p2]:
nums1.append(nums1_copy[p1])
p1 += 1
else:
nums1.append(nums2[p2])
p2 += 1
# 有剩余的部分直接全粘过去
if p1 < m:
nums1[p1 + p2:] = nums1_copy[p1:]
if p2 < n:
nums1[p1 + p2:] = nums2[p2:]
return nums1
法二:双指针 / 从后往前,优化空间O(1)
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
"""
# two get pointers for nums1 and nums2
p1 = m - 1
p2 = n - 1
# set pointer for nums1(核心指针)
p = m + n - 1
while p1 >= 0 and p2 >= 0:
if nums1[p1] < nums2[p2]:
nums1[p] = nums2[p2]
p2 -= 1
else:
nums1[p] = nums1[p1]
p1 -= 1
p -= 1
# nums2剩余的一起粘贴到nums1
nums1[:p2 + 1] = nums2[:p2 + 1]
return nums1
二、合并K个有序数组(归并)
输入: [[1,2,3], [1,2]]
输出: [1,1,2,2,3]
在 O(N log k) 的时间复杂度内完成:N 是所有数组包含的整数总数量。k 是数组的个数。
归并排序(递归)
# O(N log k) :N 是所有数组包含的整数总数量。k 是数组的个数。
# 采用归并排序算法, 拆解到最后,实际变成两个数组进行排序
class Solution(object):
def MergeSort(self, nums):
# 请牢记传入的参数是多维数组
# 此处是递归结束条件
if len(nums) <= 1:
return nums
# 取中间位置
mid = len(nums) // 2
# 此处实现递归, 记住此处得到的也是多维数组
Left = self.MergeSort(nums[:mid])
Right = self.MergeSort(nums[mid:])
# print('左:', Left[0], ',右:', Right[0])
# 要传入的参数是数组中第一个索引处的值
return self.mergeTwoLists(Left[0], Right[0]) # 合并
def mergeTwoLists(self, Left, Right):
res = [] # 存储排序后的值
a = 0 # 游标a,Left数组的第一个元素
b = 0 # 游标b,Right数组的第一个元素
while a < len(Left) and b < len(Right):
if Left[a] < Right[b]:
res.append(Left[a])
a += 1
else:
res.append(Right[b])
b += 1
# 因为存在一个到终点后,另一个还没到终点
# 这时就需要将没到终点的剩下的值添加到数组中
while a < len(Left):
res.append(Left[a])
a += 1
while b < len(Right):
res.append(Right[b])
b += 1
# 将一维数组二维化(必须!)
res = [res]
return res
用例:注意返回值和输入值,必须是二维!归并过程如下
nums = [[1, 2, 3],
[2, 3, 5],
[7, 8, 9],
[3, 5, 6]]
'''
左: [1, 2, 3] ,右: [2, 3, 5]
左: [7, 8, 9] ,右: [3, 5, 6]
左: [1, 2, 2, 3, 3, 5] ,右: [3, 5, 6, 7, 8, 9]
'''
# nums = [[1, 2, 3],
# [2, 3, 5],
# [6, 7, 9],
# [7, 8, 9],
# [3, 5, 6]]
s = Solution()
nums2d = s.MergeSort(nums)
print(nums2d) # 返回的是二维数组
nums1d = [i for j in nums2d for i in j]
print(nums1d)
归并排序 https://blog.csdn.net/IOT_victor/article/details/88365632
'''归并排序算法,a是int型列表'''
def merge_sort(a):
_merge_sort_between(a, 0, len(a) - 1)
'''递归调用函数'''
def _merge_sort_between(a, low, high):
if low < high: # 必要,特殊情况排查
mid = low + (high - low)//2
_merge_sort_between(a, low, mid)
_merge_sort_between(a, mid+1, high)
if a[mid] > a[mid+1]: # 时间优化:当前部分<=后部分时,则不需用进行merge操作
_merge(a, low, mid, high)
def _merge(a, low, mid, high):
# a[low...mid], a[mid+1...high] are sorted.
# 游标i , j 分别指向 a[low...mid], a[mid+1...high] 的第一个元素
i, j = low, mid + 1
tmp = [] # 临时数组
while i <= mid and j <= high:
if a[i] <= a[j]:
tmp.append(a[i])
i += 1
else:
tmp.append(a[j])
j += 1
# 循环结束时,会有一个子数组有剩余的数据
# if i <= mid ,说明前半个子数组有剩余的数据,start = i ,否则start = j
start = i if i <= mid else j
end = mid if i <= mid else high
# 将剩余的数据添加到 tmp 中
tmp.extend(a[start:end + 1])
# 将 tmp 中的数组拷贝回 a[low...high]
a[low:high + 1] = tmp
if __name__ == "__main__":
a1 = [3, 5, 6, 7, 8]
a2 = [2, 2, 2, 2]
a3 = [4, 3, 2, 1]
a4 = [5, -1, 9, 3, 7, 8, 3, -2, 9]
merge_sort(a1)
print(a1)
merge_sort(a2)
print(a2)
merge_sort(a3)
print(a3)
merge_sort(a4)
print(a4)