题目
- 给定两个有序整数组nums1和nums2,将nums2合并到nums1中,是的num1成为一个有序数组。
说明
- 初始化nums1和nums2的元素数量分别是m和n
- 你可以假设nums1有足够的空间,空间大小大于或者等于m+n,以次来保存nums2中的元素
示例
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
解析
- 这里解析前我们明确下数组的拷贝:
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
- 参数介绍
(1)Object src : 原数组
(2)int srcPos : 从元数据的起始位置开始
(3)Object dest : 目标数组
(4)int destPos : 目标数组的开始起始位置
(5)int length : 要copy的数组的长度
方法一:直接进行合并,合并完重新进行排序
- 代码分析
/**
* 方法一: 直接合并,然后重新排序
* @param nums1
* @param m
* @param nums2
* @param n
*/
public void merge1(int[] nums1, int m, int[] nums2, int n) {
// 因为nums1的数组长度肯定是大于nums2的
// 所以我们将nums1作为要输出的结果
// 该函数的作用参考类上注解
// 意思就是将nums2数组从0开始复制,复制到nums1中,起始位置从m(nums1数组的长度)开始,复制n条数组长度
System.arraycopy(nums2, 0, nums1, m, n);
Arrays.sort(nums1);
}
方法二:双指针(从前往后)
-
我们这里的双指针,利用的是从前向后的算法,还有一种算法是从后向前,这里我们不做详细介绍
-
我们定义两个指针,p1和p2,p1为nums1的开头,p2为nums2的开头,p是保存在nums中的当前指针
-
因为我们要直接往nums1中赋值,所以在赋值前,我们需要将nums1中的值直接拷贝出来
-
具体的解释,可以看下面的代码的注释
-
代码分析:
/**
* 方法二:双指针法,从前向后执行
* @param nums1 数组1
* @param m 数组1的长度
* @param nums2 数组2
* @param n 数组2的长度
*/
public void merge(int[] nums1, int m, int[] nums2, int n) {
// 用来指向拷贝的nums1的头
int p1 = 0;
// 用来指向nums2的头
int p2 = 0;
// 用来保存当前保存在数组的下标
int p = 0;
// 复制一个数组nums1 我们用nums1做返回值,所以需要一个新的数组用来进行判断
int[] nums_copy = new int[m];
// 进行拷贝
System.arraycopy(nums1, 0, nums_copy, 0, m);
// 当nums1数组没有遍历完且nums2数组没有遍历完
// 这时候遍历结束后 有可能会有一个数组有值没有进行赋值
while (p1 < m && p2 < n) {
// 判断nums1当前的值和nums2当前的值哪个小,哪个小就放到数组中,移动当前的下标
nums1[p++] = nums_copy[p1] < nums2[p2] ? nums_copy[p1++] : nums2[p2++];
}
// 当p1小于m的时候,表示nums1数组还有剩余 p1+P2 可以写成p
if (p1 < m) {
System.arraycopy(nums_copy, p1, nums1, p1 + p2, m + n - (p1 + p2));
}
// 当p2小于n的时候,表示nums2数组还有剩余
if (p2 < n) {
System.arraycopy(nums2, p2, nums1, p1 + p2, m + n - (p1 + p2));
}
}