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 中的元素。
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。
示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
提示:
nums1.length == m + nnums2.length == n0 <= m, n <= 2001 <= m + n <= 200109 <= nums1[i], nums2[j] <= 109
解题思路
这是一道常见的双指针问题,我们可以使用两个指针分别指向两个有序数组的末尾,然后不断比较两个指针所指向的数大小,并将其中较大的数插入到一个新的数组中。
因为本题要求我们将结果保存在第一个数组 nums1 中,所以不能使用额外的空间。
但是由于 nums1 数组后面有很多空位,因此可以从后往前遍历两个数组,利用 nums1 的后面的空位来存放最终的结果。
具体地,我们可以定义三个指针 i、j 和 k,分别指向 nums1、nums2 和 nums1 需要插入元素的下标。
-
初始化指针
i指向nums1的最后一个有值的数,即m - 1;- 指针
j指向nums2的最后一个有值的数,即n - 1; - 指针
k指向nums1数组需要插入元素的下标,即m + n - 1。 - 指针
i和j的初始值都是最后一个有值的数,而指针k的初始值是最后一个空位的下标。
- 指针
-
不断比较
nums1和nums2当前指向的数,将其中较大的数插入到nums1数组的末尾,并将指针向前移动一位。- 使用一个
while循环,在循环体内部比较nums1[i]和nums2[j]的大小, - 如果
nums1[i]大于nums2[j],则将nums1[i]插入到nums1数组的末尾(即nums1[k] = nums1[i]),并将指针i向前移动一位(即i -= 1)。 - 否则,将
nums2[j]插入到nums1数组的末尾(即nums1[k] = nums2[j]),并将指针j向前移动一位(即j -= 1)。 - 在每次插入元素之后,指针
k也需要向前移动一位(即k -= 1)。
- 使用一个
-
如果
nums2数组还有剩余的元素没有被插入到nums1中,则将其全部插入到nums1的前面。这是因为如果nums1数组先遍历完,而nums2数组还有剩余元素未插入到nums1中,那么这些元素肯定是小于nums1数组中已经遍历过的所有数的,因此可以直接插入到nums1数组的前面。
代码实现:
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
}
}