//合并两个有序数组
/*
* 两个有序整数数组nums1和nums2,将nums2合并到nums1中,使nums1成为一个有序数组
* 初始化nums1和nums2的元素数量分别为m和n。假设nums1的空间大小等于m+n,这样他就有足够的空间保存来自nums2的元素
* */
public class P15 {
public static void main(String[] args) {
int[] nums1 = new int[]{1,3,5,7,9,0,0,0,0};
int[] nums2 = new int[]{2,4,6,8};
// System.out.println(Arrays.toString(merge(nums1, 5, nums2, 4)));
// System.out.println(Arrays.toString(merge2(nums1, 5, nums2, 4)));
System.out.println(Arrays.toString(merge3(nums1, 5, nums2, 4)));
}
public static int[] merge(int[] nums1, int m, int[] nums2, int n){
//nums2从0位置开始拷贝到nums1的m位置上,拷贝长度为n
System.arraycopy(nums2, 0, nums1, m, n);
//时间 O((n+m)log(n+m))
Arrays.sort(nums1);
return nums1;
}
//双指针
//空间换时间,搞一个空数组,两个指针分别指向两个数组元素,比较大小,存进新数组中,存了的指针加1
public static int[] merge2(int[] nums1, int m, int[] nums2, int n){
//因为题目是要nums1的数组,所有这里先拷贝nums1再把nums1作为存放结果的数组
int [] nums1_copy = new int[m];
System.arraycopy(nums1, 0, nums1_copy, 0, m);
//指向nums1_copy
int p1 = 0;
//指向nums2
int p2 = 0;
//指向nums1
int p = 0;
//其中一个越界就是已经比较完了,把剩余的数据插入到后面就可以了
while(p1 < m && p2 < n){
//被选中的才++
nums1[p++] = nums1_copy[p1] < nums2[p2] ? nums1_copy[p1++] : nums2[p2++];
}
//会有某个数组还没拷贝完
if(p1 < m){
System.arraycopy(nums1_copy, p1, nums1, p, m+n-p);
}
if(p2 < n){
System.arraycopy(nums2, p2, nums1, p, m+n-p);
}
return nums1;
}
//上面的方法是需要额外空间的,可以利用nums1的空余空间进行优化
public static int[] merge3(int[] nums1, int m, int[] nums2, int n){
//从后往前遍历
//指向nums1_copy最后一个下标
int p1 = m-1;
//指向nums2最后一个下标
int p2 = n-1;
//指向nums1的最后一个下标
int p = m+n-1;
while(p1 >= 0 && p2 >= 0){
//被选中的才--
nums1[p--] = nums1[p1] > nums2[p2] ? nums1[p1--] : nums2[p2--];
}
//自己画个图想一想
System.arraycopy(nums2, 0, nums1, 0, p2+1);
return nums1;
}
}