LeetCode每日一练 —— 88. 合并两个有序数组

🌟 前言

Wassup guys!我是Edison 😎

今天是 LeetCode 上的 leetcode 88. 合并两个有序数组

Let’s get it!

在这里插入图片描述



1. 题目分析

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

示例 1:
在这里插入图片描述

示例 2:
在这里插入图片描述

示例 3:
在这里插入图片描述

2. 题目图解

非递减 的意思说明:不完全递增,数组后面的值不会比前面的值小
 
并且当 nums1nums2 合并以后,同样是 非递减顺序 的数组;
 
并且是把 nums2 合并到 nums1 中的,因为 num1 已经为 nums2 开好了的空间。

🍑 思路一

今天要介绍的第一种思路叫 归并,首先 nums1nums2 数组如下👇
在这里插入图片描述

然后我们用 下标充当指针,指针 i 指向 nums1 的第一个元素,指针 j 指向 nums2 的第一个元素;

然后再开辟一个新的数组 nums3,并且 nums3 的大小和 nums1 一样,并且指针 dst 指向 nums3 的第一个元素;如图所示👇
在这里插入图片描述

首先 i 指向的元素小于 j 指向的元素,那么就把 i 指向的较小的元素放入 num3 中,如图所示👇
在这里插入图片描述

然后指针 idst 同时向后挪动👇
在这里插入图片描述

接着 ij 指向的元素相等,那么随便把其中一个元素放入 nums3 中,假设把 j 放入 num3 中,如图所示👇
在这里插入图片描述

然后把指针 jdst 同时向后挪动👇
在这里插入图片描述

接着 i 指向的元素小于 j 指向的元素,那么就把 i 指向的较小的元素放入 num3 中,如图所示👇
在这里插入图片描述

然后指针 idst 同时向后挪动👇
在这里插入图片描述

接着 i 指向的元素还是小于 j 指向的元素,那么就把 i 指向的较小的元素放入 num3 中,如图所示👇
在这里插入图片描述

然后指针 idst 同时向后挪动👇
在这里插入图片描述
此时 nums1 中的元素已经走完了,那么直接把 nums2 中剩下的元素拿到 nums3 中去;

先把 j 指向的元素 5 拿过去,然后 jdst 同时向后挪动👇
在这里插入图片描述

最后再把 j 指向的元素 6 拿过去👇
在这里插入图片描述

这种思路就是:依次比较,每次把小的放到归并数组中。

但是这种方法最大的问题在于:需要开一个额外的数组,那么就不符合题意要求了

🍑 思路二

思路一的方法是:从左向右依次遍历数组,取小的值;
 
那么我可以选择 从右向左 取大的值,然后拿到 nums1 数组里面去,因为 nums1 数组已经开辟好了,有它俩合并到一起的空间;

还是用 下标充当指针,指针 i 指向 nums1 的最后一个 有效 元素,指针 j 指向 nums2 的最后一个 有效 元素;然后指针 dst 指向 nums1最后一个空间的位置

如图所示👇
在这里插入图片描述

首先 j 指向的元素大于 i 指向的元素,那么就把 j 指向的元素放入 dst 指向的位置中去,如图所示👇
在这里插入图片描述

然后指针 dstj 同时向前挪动一位👇(谁指向的元素大,指针就减减)
在这里插入图片描述

接着 j 指向的元素还是大于 i 指向的元素,那么就把 j 指向的元素放入 dst 指向的位置中去,如图所示👇
在这里插入图片描述

然后指针 dstj 同时向前挪动一位👇
在这里插入图片描述

此时 i 指向的元素大于 j 指向的元素,那么就把 i 指向的元素放入 dst 指向的位置中去,如图所示👇
在这里插入图片描述

然后指针 dsti 同时向前挪动一位👇
在这里插入图片描述
此时 i 指向的元素等于 j 指向的元素,那么就随便放一个元素到 dst 指向的位置中去;

假设就把 j 指向的元素放过去,然后指针 dstj 同时向前挪动一位👇
在这里插入图片描述
可以看到此时指针 j 已经把 nums2 中的元素遍历完了,再往前走就形成 越界访问 了;

所以当 j 遍历完以后,就可以结束了;

但是还有下面这种情况
在这里插入图片描述
因为 nums1 数组中的值每一个都大于 nums2的,所以指针 i 肯定会提前把 nums1 遍历完,那么此时我们就需要把 num2 中的每一个元素都拿到 nums1 的前 3 个位置上去👇
在这里插入图片描述
所以核心就是看哪个数组先遍历完!

这种方法没有开辟额外的空间,所以时间复杂度为 O ( M + N ) O(M + N) O(M+N)
 
mnums 1 中的有效元素个数;
 
nnums 2 中的有效元素个数。

3. 代码实现

📝 接口代码

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
    int i = m - 1;
    int j = n - 1;
    int dst = m + n - 1;
    // nums2 先走完的情况
    while (i >= 0 && j >= 0) {
        if (nums1[i] > nums2[j]) {
            nums1[dst] = nums1[i];
            --dst;
            --i;
        }
        else {
            nums1[dst] = nums2[j];
            --dst;
            --j;
        }
    }
    
    // nums1 先走完的情况
    while (j >= 0) {
        nums1[dst] = nums2[j];
        --dst;
        --j;
    }
}

其实还可以再简化一下👇

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
    int i = m - 1;
    int j = n - 1;
    int dst = m + n - 1;
    // nums2 先走完的情况
    while (i >= 0 && j >= 0) {
        if (nums1[i] > nums2[j]) {
            nums1[dst--] = nums1[i--];
        }
        else {
            nums1[dst--] = nums2[j--];
        }
    }
    // nums1 先走完的情况
    while (j >= 0) {
        nums1[dst--] = nums2[j--];
    }
}

🌟 提交结果
在这里插入图片描述

  • 10
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Albert Edison

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值