合并两个有序的数组
给定两个有序整数数组 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]
看到此题我们能想到的思路有两种:
1.因为nums1有足够的空间,所以直接将nums2放入nums1然后再进行排序。
代码如下:
方法一:
1 void merge(int[] nums1, int m, int[] nums2, int n) { 2 int i; 3 int j; 4 for(i=m+n-1,j=0;i>=m&&j<n;i--,j++){ //从后遍历nums1然后从后面倒着放nums2 5 nums1[i]=nums2[j]; 6 } 7 8 int k; 9 int l; 10 int tmp; 11 for(k=0;k<m+n-1;k++){ //冒泡排序 12 for(l=k+1;l<m+n;l++) 13 if(nums1[k]>nums1[l]){ 14 tmp=nums1[k]; 15 nums1[k]=nums1[l]; 16 nums1[l]=tmp; 17 } 18 } 22 }
23 public static void main(String[] args) {
24 int[] nums1 = new int[6];
25 int[] nums2 = new int[2];
26 nums1[0] = 1;
27 nums1[1] = 2;
28 nums1[2] = 3;
29 nums1[3] = 5;
30 nums2[0] = 2;
31 nums2[1] = 6;
32 merge(nums1,4,nums2,2);
33 for(int b = 0;b < nums1.length;b++) {
34 System.out.println(nums1[b]);
35 }
36 }
方法二:
1 public static void merge(int[] nums1, int m, int[] nums2, int n) { 2 for(int i = 0;i < n;i++){ //拿着nums2的元素去插入 3 int tem = nums2[i]; 4 int j = 0; 5 while(tem >= nums1[j] && j < m){ //若nums2得的元素大于nums1的元素 6 j++; //nums2往后移 7 } 8 m++; //移向nums1的下一个元素 9 for(int k = m - 1;k > j;k--){ 10 nums1[k] = nums1[k-1]; //nums1往后移 11 } 12 nums1[j] = tem; //nums2放入当前找到的位子 13 } 14 } 15 16 public static void main(String[] args) { 17 int[] nums1 = {1,2,3,0,0,0}; 18 int[] nums2 = {2,3,8}; 19 20 merge(nums1,3,nums2,3); 21 for(int k = 0;k < nums1.length;k++) { 22 System.out.println(nums1[k]); 23 } 24 25 }
结果如下:
从上面的代码中我们可以看到先将nums2放入nums2,然后再排序。方法一相当与用了两次双重循环,时间复杂度是否优点大呢??而且这样是否浪费了题意呢??那再读一遍题:给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。有没有更好一点解决办法呢?当然有:
2.我们先申请一个有m+n 大的数组,将nums1和nums2同时往新的数组里面放,因为他们都是有序的,所以就判断然后加就好了,这样就会避免双重循环给的复杂度太高,而且不“浪费题意”。我们看代码。
代码如下:
方法三:
1 void merge(int[] nums1, int m, int[] nums2, int n) { 2 int[] nums = new int[m + n];//申请新的数组nums 3 int index = 0; 4 int i = 0; 5 int j = 0; 6 while (i < m && j < n ) { //两个数组同时判断 7 if (nums1[i] <= nums2[j]) 8 nums[index++] = nums1[i++]; 9 else 10 nums[index++] = nums2[j++]; 11 12 } 13 if ( i < m) { //这是为了nums1的长度比nums2大上面的while循环已经不能再判断。 14 while (i<m) 15 nums[index++] = nums1[i++]; //nums2已经放完,直接将nums1剩下的往里面放 16 } 17 if (j < n) { //这是为了nums2的长度比nums1大上面的while循环已经不能再判断。 18 while (j<n) 19 nums[index++] = nums2[j++];//nums1已经放完,直接将nums2剩下的往里面放 20 } 21 System.arraycopy(nums,0,nums1,0,nums.length - n); //给nums1赋去
22 }
23 public static void main(String[] args) {
24 int[] nums1 = {1,2,3,0,0,0};
25 int[] nums2 = {2,3,8};
26
27 merge(nums1,3,nums2,3);
28 for(int k = 0;k < nums1.length;k++) {
29 System.out.println(nums1[k]);
30 }
31 }
结果如下:
从上面的代码中,我们可以看到它很巧妙的用到了nums1和nums2是有序的条件。而且最后也将最终的新的数组nums赋给了nums1也是实现了假定nums1有m+n大的空间,可以合并nums1和nums2了。