88.合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1nums2,另有两个整数 mn ,分别表示 nums1nums2 中的元素数目。

请你 合并 nums2nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n

示例 1:

1
2
3
4
输入: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 中的元素。

合并数组,并且让他们按非递减顺序,需要比较和遍历数组中的元素

巧妙设置了while (p1 >= 0 || p2 >= 0)这个条件来判断是否遍历完成,利用cur这个临时变量来存储当前结果,让代码更加清晰,最后使用逆序双指针的方式完成遍历

Solution1:双指针比较,创造一个新的数组

方法一没有利用数组 nums1nums2 已经被排序的性质。为了利用这一性质,我们可以使用双指针方法。这一方法将两个数组看作队列,每次从两个数组头部取出比较小的数字放到结果中。

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
class Solution {
// merge方法接受两个有序数组nums1和nums2,以及它们各自的元素数量m和n
public void merge(int[] nums1, int m, int[] nums2, int n) {
// p1和p2是两个数组的初始索引位置
int p1 = 0, p2 = 0;
// 创建一个新的数组sorted,用于存放合并后的有序数组
int[] sorted = new int[m + n];
// cur用于暂存当前要添加到sorted数组中的元素
int cur;
// 当任一数组中还有元素未被处理时,继续循环
while (p1 < m || p2 < n) {
if (p1 == m) {
// 如果nums1中的元素已经全部处理完毕,剩下的都是nums2中的元素
cur = nums2[p2++];
} else if (p2 == n) {
// 如果nums2中的元素已经全部处理完毕,剩下的都是nums1中的元素
cur = nums1[p1++];
} else if (nums1[p1] < nums2[p2]) {
// 如果nums1当前的元素小于nums2当前的元素,取nums1的元素
cur = nums1[p1++];
} else {
// 否则,取nums2的元素
cur = nums2[p2++];
}
// 将选出的元素添加到sorted数组中的正确位置
sorted[p1 + p2 - 1] = cur;
}
// 将sorted数组中的元素复制回nums1,完成合并
for (int i = 0; i != m + n; ++i) {
nums1[i] = sorted[i];
}
}
}


Solution:逆向双指针

方法2之所以需要辅助数组,是怕把num1数组直接覆盖掉,如果我们从后往前插入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
class Solution {
// merge方法接受两个数组nums1和nums2,以及它们的有效元素数量m和n
public void merge(int[] nums1, int m, int[] nums2, int n) {
// p1是指向nums1中最后一个有效元素的指针
int p1 = m - 1;
// p2是指向nums2中最后一个有效元素的指针
int p2 = n - 1;
// tail是指向合并后nums1数组中最后一个元素的位置
int tail = m + n - 1;
// cur用于暂存当前需要放入nums1数组中的元素
int cur;
// 当任一数组还有元素未被检查时,进行循环
while (p1 >= 0 || p2 >= 0) {
// 如果nums1已经没有元素(p1 == -1),直接取nums2的元素
if (p1 == -1) {
cur = nums2[p2--];
// 如果nums2已经没有元素(p2 == -1),直接取nums1的元素
} else if (p2 == -1) {
cur = nums1[p1--];
// 如果nums1当前元素大于nums2当前元素,取nums1的元素
} else if (nums1[p1] > nums2[p2]) {
cur = nums1[p1--];
// 否则,取nums2的元素
} else {
cur = nums2[p2--];
}
// 将选出的元素放到nums1的当前tail位置,然后将tail指针前移
nums1[tail--] = cur;
}
}
}