P15-合并两个有序数组-双指针
//合并两个有序数组 /* * 两个有序整数数组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; } }