88.合并两个有序数组
题目说明
难度简单
给你两个按 非递减顺序 排列的整数数组 nums1
**和 nums2
,另有两个整数 m
和 n
,分别表示 nums1
和 nums2
中的元素数目。
请你 合并 nums2
到 nums1
中,使合并后的数组同样按 非递减顺序** 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1
中。为了应对这种情况,nums1
的初始长度为 m + n
,其中前 m
个元素表示应合并的元素,后 n
个元素为 0
,应忽略。nums2
的长度为 n
。
示例 1:
1
2
3
4
5
输入: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 中的元素。
示例 2:
1
2
3
4
5
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。
示例 3:
1
2
3
4
5
6
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
提示:
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
109 <= nums1[i], nums2[j] <= 109
解题思路
这是一道常见的双指针问题,我们可以使用两个指针分别指向两个有序数组的末尾,然后不断比较两个指针所指向的数大小,并将其中较大的数插入到一个新的数组中。
初始化指针:设置三个指针
i
、j
和k
,其中i
指向nums1
数组的最后一个元素,j
指向nums2
数组的最后一个元素,k
指向nums1
数组末尾的空位(即m + n - 1
,因为nums1
的前m
个元素已经存在,需要在它们后面插入nums2
的元素)。- 合并过程:使用
while
循环,只要i
和j
都大于等于0(即两个数组都还有元素未比较),就进行以下操作:- 比较
nums1[i]
和nums2[j]
的大小。 - 如果
nums1[i]
大于nums2[j]
,则将nums1[i]
移动到nums1[k]
的位置,并将i
和k
都向前移动一位。 - 如果
nums1[i]
小于或等于nums2[j]
,则将nums2[j]
移动到nums1[k]
的位置,并将j
和k
都向前移动一位。
- 比较
处理剩余元素:当
nums2
数组的所有元素都被比较过后,如果nums1
数组还有剩余的元素未比较(即i < 0
),则nums2
中剩余的元素直接插入到nums1
的前面。这部分通过另一个while
循环完成,循环条件是j >= 0
,循环体是将nums2[j]
插入到nums1[k]
,同时j
和k
向前移动一位。- 结束函数:由于
nums1
是inout
参数,所以对它的修改会直接反映到原数组上,不需要额外的返回值。函数没有显式返回语句,因为在 Swift 中,最后一行表达式的值会被用作函数的返回值,但在这个函数中,没有需要返回的值。
这个函数的时间复杂度是 O(n),其中 n 是 nums2
的长度,因为每个元素最多被比较一次。空间复杂度是 O(1),因为除了输入数组外,没有使用额外的存储空间。
代码实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func merge(_ nums1: inout [Int], _ m: Int, _ nums2: [Int], _ n: Int) {
var i = m - 1 // 初始化 nums1 数组指针 i,指向数组最后一个数
var j = n - 1 // 初始化 nums2 数组指针 j,指向数组最后一个数
var k = m + n - 1 // 初始化 nums1 数组需要插入元素的下标 k,指向数组最后一个空位
while i >= 0 && j >= 0 { // 只要两个数组都还没遍历完
if nums1[i] > nums2[j] { // 如果 nums1 当前指向的数比 nums2 当前指向的数大
nums1[k] = nums1[i] // 将 nums1 当前指向的数插入到 nums1 数组的最后
i -= 1 // nums1 指针左移一位
} else {
nums1[k] = nums2[j] // 将 nums2 当前指向的数插入到 nums1 数组的最后
j -= 1 // nums2 指针左移一位
}
k -= 1 // 插入元素的下标左移一位
}
// 如果 nums2 数组还有剩余的元素没有被插入到 nums1 中,则将其全部插入到 nums1 的前面
while j >= 0 {
nums1[k] = nums2[j]
j -= 1
k -= 1
}
}
本文由作者按照 CC BY 4.0 进行授权