这是很容易想到的一种思路,用双指针思想分别遍历比较两个数组中数的大小,将较小的那个数依次放入新创建的数组中,最后将该数组拷贝到 nums1
代码如下:
public static void merge(int[] nums1, int m, int[] nums2, int n) {
int[] ans = new int[m + n];
int p1 = 0, p2 = 0, p3 = 0;
while (p1 < m && p2 < n) {
if (nums1[p1] <= nums2[p2]) {
ans[p3] = nums1[p1];
p1++;
} else {
ans[p3] = nums2[p2];
p2++;
}
p3++;
}
if (p1 == m) {
for (int i = p2; i < n; i++) {
ans[p3] = nums2[i];
p3++;
}
} else {
for (int i = p1; i < m; i++) {
ans[p3] = nums1[i];
p3++;
}
}
System.arraycopy(ans, 0, nums1, 0, m + n);
}
问题:没有利用好 nums1 数组初始长度为 m + n 的特点,且新创建数组占用内存
优化:从后往前确认数组,直接在 nums1 上进行变化,注意 nums2 未完全插入的情况
代码如下:
public static void merge(int[] nums1, int m, int[] nums2, int n) {
m--;
n--;
while (m >= 0 && n >= 0) {
nums1[m + n + 1] = nums2[n] >= nums1[m] ? nums2[n--] : nums1[m--];
}
while (n >= 0) {
nums1[m + n + 1] = nums2[n--];
}
}
这种思路简单且代码量比较少,但是没有利用到题目中数组 非递减顺序 的条件
代码如下:
public static void merge(int[] nums1, int m, int[] nums2, int n) {
System.arraycopy(nums2, 0, nums1, m, n);
Arrays.sort(nums1);
}
源码:
参数:
src:源数组
srcPos:源数组要复制的起始位置
dest:目标数组
destPos:目标数组要复制的起始位置
length:要复制的数组长度
用法:
public static void main(String[] args) {
int[] arr1 = new int[]{0, 1, 2, 5};
int[] arr2 = new int[4];
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
System.out.println(Arrays.toString(arr2));
}
//输出:[0, 1, 2, 5]
源码:
从源码可以看出,Arrays.copyOf() 实际上就是调用的 System.arraycopy()
用法:
public static void main(String[] args) {
int[] arr1 = new int[]{0, 1, 2, 5};
int[] arr2 = Arrays.copyOf(arr1, arr1.length);
System.out.println(Arrays.toString(arr2));
}
//输出:[0, 1, 2, 5]
用法:
public static void main(String[] args) {
int[] arr1 = new int[]{0, 1, 2, 5};
int[] arr2 = arr1.clone();
System.out.println(Arrays.toString(arr2));
}
//输出:[0, 1, 2, 5]
注意在思路一中是不能用 clone() 来将新创建的数组拷贝给 nums1 的,这里的拷贝是给形参 nums1 重新赋值,改变了引用对象,并不会改变实参 nums1
这点与 Java 的值传递有关,可参考视频进行理解:
Java 到底是值传递还是引用传递
关于 clone() 的更多内容可参考文章:
Java 中 clone 方法详解