leetcode第88题,合并两个有序数组。采用双指针的算法来完成。

Leetcode 88合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1nums2,另有两个整数 m n ,分别表示 nums1nums2 中的元素数目。

请你 合并 nums2nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n

示例 1:

1输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
2输出:[1,2,2,3,5,6]
3解释:需要合并 [1,2,3] 和 [2,5,6] 。
4合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

示例 2:

1输入:nums1 = [1], m = 1, nums2 = [], n = 0
2输出:[1]
3解释:需要合并 [1] 和 [] 。
4合并结果是 [1] 。

示例 3:

1输入:nums1 = [0], m = 0, nums2 = [1], n = 1
2输出:[1]
3解释:需要合并的数组是 [] 和 [1] 。
4合并结果是 [1] 。
5注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。

提示:

  • nums1.length == m + n
  • nums2.length == n
  • 0 <= m, n <= 200
  • 1 <= m + n <= 200
  • -109 <= nums1[i], nums2[j] <= 109

**进阶:**你可以设计实现一个时间复杂度为 O(m + n) 的算法解决此问题吗?

思路

可以直接利用函数的快速排序。

  1. nums2的元素放到nums1中,形成一个新的只有nums1的序列
  2. 然后对nums的序列快速排序

解题

 1class Solution {
 2    //合并成一个数组,然后快速排序
 3    public void merge(int[] nums1, int m, int[] nums2, int n) {
 4        for(int i = 0; i < n; i++)
 5        {
 6            nums1[m + i] = nums2[i];
 7        }
 8        Arrays.sort(nums1);
 9    }
10}

其实还可以利用递增的关系(双指针)

  1. 每个数组头部头有一个指针指向第一位,创建一个临时数组
  2. 比较双指针所在的值,会出现三种结果。如果相等,默认取nums2的元素,并且指针往后移动一位;如果不相等,取指针指向小的那位,并且指针往后移动一位。
  3. 直到两个指针全部移动完成
 1class Solution {
 2    //双指针做法,增加一个临时数组
 3    public void merge(int[] nums1, int m, int[] nums2, int n) {
 4        int k = m + n;
 5        int[] tmp = new int[k];
 6        for(int index = 0, nums1Index = 0, nums2Index = 0; index < k; index++)
 7        {
 8            if(nums1Index >= m)//nums1数组元素取完
 9            {
10                tmp[index] = nums2[nums2Index++];
11            }else if(nums2Index >= n)//nums2数组元素取完
12            {
13                tmp[index] = nums1[nums1Index++];
14            }else if(nums1[nums1Index] < nums2[nums2Index])
15            //nums1元素小于nums2元素
16            {
17                tmp[index] = nums1[nums1Index++];
18            }else//nums2元素小于nums1元素
19            {
20                tmp[index] = nums2[nums2Index++];
21            }
22        }
23        //重新赋值给nums1
24        for(int i = 0; i < k; i++)
25        {
26            nums1[i] = tmp[i];
27        }
28    }
29
30}

由于这里nums1存在一个m+n的元素存放,那么其实可以利用上这个空间,不需要临时tmp数组

还是利用双指针做法

  1. 每个数组头尾部有一个指针指向最后一位
  2. 比较双指针所在的值,会出现三种结果。如果相等,默认取nums2的元素,并且指针往前移动一位;如果不相等,取指针指向大的那位,并且指针往前移动一位。把元素存放到nums1的数组中
  3. 直到两个指针全部移动完成
 1class Solution {
 2    //双指针做法,利用nums1的空间,从后往前降序排列
 3    public void merge(int[] nums1, int m, int[] nums2, int n) {
 4        int k = m + n;
 5        for(int index = k-1, nums1Index = m - 1, nums2Index = n -1;
 6            index >= 0; index--)
 7        {
 8            if(nums1Index < 0)//nums1元素已经取完
 9            {
10                nums1[index] = nums2[nums2Index--];
11            }else if(nums2Index < 0)//nums2元素已经取完
12            {
13                break;
14            }else if(nums1[nums1Index] > nums2[nums2Index])
15            //nums1元素值大于nums2,取nums1值
16            {
17                nums1[index] = nums1[nums1Index--];
18            }else
19            {
20                //nums2元素值大于等于nums1,取nums2值
21                nums1[index] = nums2[nums2Index--];
22            }
23        }
24    }
25
26}