每天一道leetcode88-合并两个有序数组

9,584 阅读6分钟

考试结束,班级平均分只拿到了年级第二,班主任于是问道:大家都知道世界第一高峰珠穆朗玛峰,有人知道世界第二高峰是什么吗?正当班主任要继续发话,只听到角落默默想起来一个声音:”乔戈里峰

前言

2018.11.16号打卡
明天的题目leetcode66:
https://leetcode-cn.com/problems/plus-one/

题目

每天一道leetcode88-合并两个有序数组
分类:链表
中文链接:
https://leetcode-cn.com/problems/merge-sorted-array/
英文链接
https://leetcode.com/problems/merge-sorted-array/

题目详述

给定两个有序整数数组 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]

题目详解

使用额外空间的思路

  • 混合插入有序数组,由于两个数组都是有序的,所有只要按顺序比较大小即可。最先想到的方法是建立一个m+n大小的新数组,然后逐个从A和B数组中取出元素比较,把较小的加入新数组,然后在考虑A数组有剩余和B数组有剩余的两种情况,最后在把新数组的元素重新赋值到A数组中即可。

代码

 1class Solution {
2    public void merge(int[] nums1, int m, int[] nums2, int n) {
3        int [] result = new int[m+n];
4        int i =0,j=0,k=0;
5        while(i < m && j < n)
6        {
7            if(nums1[i] < nums2[j]){
8                result[k++] = nums1[i++];
9            }else{
10                result[k++] = nums2[j++];
11            }
12        }
13        if(i != m)
14        {
15            while(i < m)
16            {
17                result[k++] = nums1[i++];
18            }
19        }
20        if(j != n)
21        {
22            while(j < n)
23            {
24                result[k++] = nums2[j++];
25            }
26        }
27        k = 0;
28        for(i=0;i<nums1.length;i++)
29            nums1[i] = result[k++];
30
31    }
32}

代码讲解

  • 5-12行,比较num1数组与nums2数组,哪个小,就存入result中
  • 13-26行 就是两个数组,可能有一个没遍历完,那么把这个没遍历完的继续添加到result数组后面
  • 28-29行 就是把result数组复制到nums1中。

不使用额外空间的思路

  • 由于合并后A数组的大小必定是m+n,所以从最后面开始往前赋值,先比较A和B中最后一个元素的大小,把较大的那个插入到m+n-1的位置上,再依次向前推。如果A中所有的元素都比B小,那么前m个还是A原来的内容,没有改变。如果A中的数组比B大的,当A循环完了,B中还有元素没加入A,直接用个循环把B中所有的元素覆盖到A剩下的位置。

代码

 1class Solution {
2    public void merge(int[] nums1, int m, int[] nums2, int n) {
3        int k = m + n - 1;
4        int i = m-1;int j = n-1;
5        while(i >=0 && j >= 0)
6        {
7            if(nums1[i] > nums2[j])
8            {
9                nums1[k--] = nums1[i--];
10            }else{
11                nums1[k--] = nums2[j--];
12            }
13        }
14        if(i > 0)
15        {
16            while(i >= 0)
17            {
18                nums1[k--] = nums1[i--];
19            }
20        }
21        if(j >= 0)
22        {
23            while(j >= 0)
24            {
25                nums1[k--] = nums2[j--];
26            }
27        }
28    }
29}

代码讲解

  • 5-13行就是从数组nums1和数组nums2的后面开始遍历,谁大就把谁存到nums1的后面(这里注意看示例,nums1的后面是一堆0,代表空闲的空间,m和nums1的数组长度是不一样的~
  • 14-20行 就是如果nums1前面有数字没遍历完,那么就把nums1的数字继续保留到nums1中,其实这6行代码可以不要,因为nums1的数字就是有序的,不需要再次复制了,nums1的前面的数字已经存在于nums1中了;
  • 21-27行 就是如果nums2前面还有数字没遍历完,那么就把nums2中数字复制到nums1中,这里是必须要要用到,因为nums2中数字可不在nums1中。

结束语

2018.11.16号打卡

作者乔戈里亲历2019秋招,哈工大计算机本硕,百度准入职java工程师,欢迎大家关注我的微信公众号:程序员乔戈里,公众号有3T编程资源,以及我和我朋友(准入职百度C++工程师)在秋招期间整理的近200M的面试必考的java与C++面经,并有每天一道leetcode打卡群与技术交流群,欢迎关注。