LeetCode88. 合并两个有序数组 + 合并K个有序数组

11 篇文章 0 订阅

一、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)

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值