victory的博客

长安一片月,万户捣衣声

0%

leetcode | 88.合并两个有序数组

88.合并两个有序数组

题目描述

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

题目链接

思路

  1. 归并
    设置两个指针i,j,从头开始遍历两个数组,哪个指针指向位置的元素较小则加入结果列表中,该指针后移,…,依次类推。
    如果两个数组长度不一样,循环结束后,需要将长度较长的数组剩余元素加入结果列表。
  2. 双指针
    由于题目所给数组均有序,因此可以设置两个指针分别指向两个数组第一个元素,判断两个指针指向位置的元素大小,每次将较小的加入结果列表中。
    如果某一个数组先遍历结束,后续只需要遍历另一个数组的剩余元素并将其加入结果列表中。
  3. 先将数组nums2放进数组nums1的尾部,然后直接对整个数组进行排序
  4. 逆向双指针
    对双指针法进行改进,从后往前遍历数组,每次将较大元素放入结果列表中。
    在双指针法中,我们需要创建长度为m+n的新数组保存结果,因为如果直接在nums1上保存,会覆盖nums1的元素。
    与双指针方法不同的是,该方法可以原地地在nums1上保存结果(从后往前放入元素不会产生覆盖)。

    代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    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: None Do not return anything, modify nums1 in-place instead.
    """
    i = 0
    j = 0
    result = []
    while i < m and j < n:
    if nums1[i] < nums2[j]:
    result.append(nums1[i])
    i += 1
    elif nums1[i] >= nums2[j]:
    result.append(nums2[j])
    j += 1

    if m - i != 0:
    for k in range(m - (m - i), m):
    result.append(nums1[k])
    if n - j != 0:
    for p in range(n - (n - j), n):
    result.append(nums2[p])

    nums1[:] = result

    def merge1(self, nums1, m, nums2, n):
    # 先将数组nums2放进数组nums1的尾部,然后直接对整个数组进行排序
    nums1[m:] = nums2
    quick_sort(nums1, 0, len(nums1) - 1)

    def merge2(self, nums1, m, nums2, n):
    sorted = []
    p1, p2 = 0, 0
    while p1 < m or p2 < n:
    if p1 == m:
    sorted.append(nums2[p2])
    p2 += 1
    elif p2 == n:
    sorted.append(nums1[p1])
    p1 += 1
    elif nums1[p1] < nums2[p2]:
    sorted.append(nums1[p1])
    p1 += 1
    else:
    sorted.append(nums2[p2])
    p2 += 1
    nums1[:] = sorted

    def merge3(self, nums1, m, nums2, n):
    """逆向双指针"""
    p1, p2 = m - 1, n - 1
    tail = m + n - 1
    while p1 >= 0 or p2 >= 0:
    if p1 == -1: # 如果nums1数组已经遍历完毕,遍历nums2中的剩余元素
    nums1[tail] = nums2[p2]
    p2 -= 1
    elif p2 == -1: # 如果nums2数组已经遍历完毕,遍历nums1中的剩余元素
    nums1[tail] = nums1[p1]
    p1 -= 1
    elif nums1[p1] > nums2[p2]:
    nums1[tail] = nums1[p1]
    p1 -= 1
    else:
    nums1[tail] = nums2[p2]
    p2 -= 1

    tail -= 1


    def quick_sort(arr, low, high):
    """快速排序"""
    if low < high:
    pivot = partition(arr, low, high)
    quick_sort(arr, low, pivot - 1)
    quick_sort(arr, pivot + 1, high)


    def partition(arr, low, high):
    pivot_key = arr[low]
    while low < high:
    while low < high and arr[high] >= pivot_key:
    high -= 1
    arr[low], arr[high] = arr[high], arr[low]
    while low < high and arr[low] <= pivot_key:
    low += 1
    arr[low], arr[high] = arr[high], arr[low]
    return low


    if __name__ == "__main__":
    slt = Solution()
    nums1 = [1, 2, 3, 0, 0, 0]
    nums2 = [2, 5, 6]
    # slt.merge(nums1, 3, nums2, 3)
    # slt.merge1(nums1, 3, nums2, 3)
    # slt.merge2(nums1, 3, nums2, 3)
    slt.merge3(nums1, 3, nums2, 3)
    print(nums1)