【LeetCode刷题日志】88.合并两个有序数组

news2025/1/13 5:51:08

  • 🎈个人主页:库库的里昂
  •  🎐C/C++领域新星创作者
  •  🎉欢迎 👍点赞✍评论⭐收藏
  • ✨收录专栏:LeetCode 刷题日志
  • 🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗

目录

1.题目描述

2.解题思路+代码实现

方法一:直接合并后排序

思路及算法:

代码实现:

方法二:双指针

思路及算法:

代码实现:

方法三:逆向双指针

思路及算法:

代码实现:


1.题目描述

OJ链接 【leetcode 题号:88.合并两个有序数组】【难度:简单】

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

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

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

示例 1:

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

示例 2:

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

示例 3:

输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 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) 的算法解决此问题吗?

2.解题思路+代码实现

方法一:直接合并后排序
思路及算法:

这种方法最直观,先将数组nums2放进数组nums1的尾部,然后直接对整个数组进行排序。

代码实现:
int cmp(int* a, int* b) {
    return *a - *b;
}

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    for (int i = 0; i != n; ++i) {
        nums1[m + i] = nums2[i];
    }
    qsort(nums1, nums1Size, sizeof(int), cmp);
}

复杂度分析

  • 时间复杂度:O((m+n)log(m+n))。 排序序列长度为m+n,套用快速排序的时间复杂度即可,平均情况为O((m+n)log(m+n))。
  • 空间复杂度:O(log(m+n))。排序序列长度为m+n,套用快速排序的空间复杂度即可,平均情况为O(log⁡(m+n))。
方法二:双指针
思路及算法:

方法一没有利用数组nums1nums2已经被排序的性质。为了利用这一性质,我们可以使用双指针方法。这一方法将两个数组看作队列,每次从两个数组头部取出比较小的数字放到结果中。如下面的动画所示:

我们为两个数组分别设置一个指针p1​与p2​来作为队列的头部指针。

代码实现:
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int p1 = 0, p2 = 0;
    int sorted[m + n];
    int cur;
    while (p1 < m || p2 < n) {
        if (p1 == m) {
            cur = nums2[p2++];
        } else if (p2 == n) {
            cur = nums1[p1++];
        } else if (nums1[p1] < nums2[p2]) {
            cur = nums1[p1++];
        } else {
            cur = nums2[p2++];
        }
        sorted[p1 + p2 - 1] = cur;
    }
    for (int i = 0; i != m + n; ++i) {
        nums1[i] = sorted[i];
    }
}

复杂度分析

  • 时间复杂度:O(m+n)。 指针移动单调递增,最多移动m+n次,因此时间复杂度为O(m+n)。
  • 空间复杂度:O(m+n)。 需要建立长度为m+n的中间数组sorted。
方法三:逆向双指针
思路及算法:

方法二中,之所以要使用临时变量,是因为如果直接合并到数组nums1中,nums1中的元素可能会在取出之前被覆盖。那么如何直接避免覆盖nums1中的元素呢?观察可知,nums1的后半部分是空的,可以直接覆盖而不会影响结果。因此可以指针设置为从后向前遍历,每次取两者之中的较大者放进nums1的最后面。

严格来说,在此遍历过程中的任意一个时刻,nums1数组中有m−p1−1个元素被放入nums1的后半部,nums2数组中有n−p2−1个元素被放入nums1的后半部,而在指针p1的后面,nums1数组有 m+n−p1−1个位置。由于

m+n−p1−1≥m−p1−1+n−p2−1等价于p2≥−1

永远成立,因此p1后面的位置永远足够容纳被插入的元素,不会产生p1的元素被覆盖的情况。

代码实现:
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int p1 = m - 1, p2 = n - 1;
    int tail = m + n - 1;
    int cur;
    while (p1 >= 0 || p2 >= 0) {
        if (p1 == -1) {
            cur = nums2[p2--];
        } else if (p2 == -1) {
            cur = nums1[p1--];
        } else if (nums1[p1] > nums2[p2]) {
            cur = nums1[p1--];
        } else {
            cur = nums2[p2--];
        }
        nums1[tail--] = cur;
    }
}

复杂度分析

  • 时间复杂度:O(m+n)。 指针移动单调递减,最多移动m+n次,因此时间复杂度为 O(m+n)。
  • 空间复杂度:O(1)。 直接对数组nums1原地修改,不需要额外空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1149556.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

markMan(马克鳗)前端标注工具

马克鳗一款很好用的标注、测量工具&#xff0c;前端必备神器。当需求给我们的原型没有标注颜色&#xff0c;尺寸数据&#xff0c;我们就可以用马克鳗自己标出来。 1.进入官网进行下载 官网网址&#xff1a;http://www.getmarkman.com/ 功能演示&#xff1a; 打开markMan需要拖…

企业金蝶KIS软件服务器中了locked勒索病毒怎么办,勒索病毒解密

最近一段时间&#xff0c;网络上的locked勒索病毒又开始了新一波的攻击&#xff0c;给企业的正常生产生活带来了严重影响。经过最近一段时间云天数据恢复中心对locked勒索病毒的解密&#xff0c;为大家整理了以下有关locked勒索病毒的相关信息。近期locked勒索病毒主要攻击金蝶…

Xamarin.Forms更改AndroidManifest.xml导致错误:没有兼容的代码在线程上运行

想在APP中加一个打开摄像头的功能&#xff0c;按照该博主的方法&#xff1a;https://blog.csdn.net/zhenweied09/article/details/82287761 设置好后&#xff0c;再运行就出现上图的错误&#xff0c;于是查找原因&#xff0c;定位到是更改AndroidManifest.xml文件导致的&#…

用软件模拟IPC的RTSP流,对接烟火识别算法服务,做实时的烟火检测、人员入侵检测、抽烟检测等算法

最近在研发烟火识别的算法&#xff0c;想要检验算法集成到视频分析服务之后的效果&#xff0c;发现线上的摄像机很难发现火情&#xff0c;有的很长时间都不会有检测的结果&#xff0c;于是我就需要用已经被检验过的视频文件&#xff0c;模拟一路IPC的RTSP流&#xff0c;来测试烟…

Spring@Lazy是如何解决构造函数循环依赖问题

Spring实例化源码解析之循环依赖CircularReference这章的最后我们提了一个构造函数形成的循环依赖问题&#xff0c;本章就是讲解利用Lazy注解如何解决构造函数循环依赖和其原理。 准备工作 首先创建两个构造函数循环依赖的类&#xff0c;TestA和TestB&#xff0c;代码如下&am…

MFC 重绘Button按钮,使用png、jpg图片贴图

使用MFC实现Button按钮实现png和jpg贴图功能&#xff0c;底部有实现代码的工程链接&#xff0c;免费下载 此工程使用了第三方库GDI 实现文件如下&#xff1a; CGdiPlusBitmap.h GdipButton.cpp GdipButton.h MemDC.h 一、在启动cpp里面增加GDI初始化与释放 Gdiplus::Gdiplus…

“2024中国信息通信展览会”促进全球通信领域交流合作的重要桥梁

2024中国国际信息通信展览会&#xff08;PT展&#xff09; China International PT Expo 时间:2024年9月25-27日 地点:北京.国家会议中心 主办单位&#xff1a; 工业和信息化部 协办单位&#xff1a; 中国通信标准化协会 中国通信企业协会 中国电信 中国移动 中国联通…

【Java每日一题】——第四十三题:编程用多态实现打印机.。分为黑白打印机和彩色打印机,不同类型的打印机打印效果不同。(2023.10.30)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

[Unity][VR]透视开发系列4-解决只看得到Passthrough但看不到Unity对象的问题

【视频资源】 视频讲解地址请关注我的B站。 专栏后期会有一些不公开的高阶实战内容或是更细节的指导内容。 B站地址: https://www.bilibili.com/video/BV1Zg4y1w7fZ/ 我还有一些免费和收费课程在网易云课堂(大徐VR课堂): https://study.163.com/provider/480000002282025/…

你还在找什么赚钱的项目吗?真心话坦白局系统源码

它具有匿名信息的神秘感 但又会给你一点小提示 能让你有无限挖掘下去的好奇感 也能让你说出那些不敢说出口的话 敢来一场坦白局吗&#xff01; 坦白局这个功能类似于悄悄话&#xff0c;只不过是匿名的悄悄话。 有时候我们有些话是开不了口的&#xff0c;坦白局给了我们一个…

颠覆传统:跨境电商借助DTC模式掀起新浪潮

跨境电商领域正经历着一场前所未有的革命&#xff0c;直接到消费者&#xff08;Direct-to-Consumer&#xff0c;DTC&#xff09;模式崭露头角&#xff0c;成为这一领域的一股强大力量。 传统的跨境电商模式受到了挑战&#xff0c;DTC模式正重新定义着全球电商的规则和格局。本…

STM32单片机智能小车一PWM方式实现小车调速和转向

目录 1. 电机模块开发 2. 让小车动起来 3. 串口控制小车方向 4. 如何进行小车PWM调速 5. PWM方式实现小车转向 1. 电机模块开发 L9110s概述 接通VCC&#xff0c;GND 模块电源指示灯亮&#xff0c; 以下资料来源官方&#xff0c;具体根据实际调试 IA1输入高电平&#xff…

销售流程管理实践及工具-Leangoo免费看板工具

销售管理既可以提高企业的销售业绩&#xff0c;又可以跟客户建立良好的关系。所以企业实施销售管理是非常有必要的。Leangoo免费看板不仅可以管理任务&#xff0c;它也可以成为一个绝佳的销售管理工具&#xff0c;帮助销售理清思路&#xff0c;达成目标。 首先在Leangoo中创建…

如何用加密狗保护工业软件核心技术?

工业软件的抄袭风险 1.1 反编译直窥软件的核心 工业软件代表着技术进步和创新&#xff0c;其中蕴含的算法、数据处理流程和功能模块往往是企业的核心竞争力。但随着技术的发展&#xff0c;反编译工具变得越来越先进&#xff0c;让不法分子可以“解剖”软件&#xff0c;看到它的…

Fegin ----微服务 SpringCloud

@FeignClient 是一个注解,用于创建一个声明式的 REST 客户端,用于访问其他服务的 REST API。通过 Feign Client,可以将远程服务的 API 当做本地服务进行调用,Feign Client 能够自动生成 API 客户端的实现类,在使用 API 时,只需要像调用本地方法一样调用即可。 @FeignClie…

Linux(Centos7)防火墙端口操作记录

1、nginx -t #Nginx配置文件检查 上述截图代表检查没问题 上述截图检查配置文件配置错误&#xff0c;并提示错误文件位置 2、systemctl restart nginx #重启Nginx 重启Nginx失败 3、systemctl status nginx.service #查看Nginx服务状态 80端口被占导致服务启动失败 4、n…

常见的22个软件测试面试题(含答案解析)

大家好&#xff0c;我是大圣。今天大圣给大家列举了API测试的22个面试题&#xff0c;快来看看吧。 1、什么是API? API是允许两个应用程序相互通信的代码。API使开发人员能够发出特定的调用或请求来发送或接收信息。 2、什么是以API为中心的应用程序? 以API为中心的应用程…

Java进阶(Set)——面试时Set常见问题解读 结合源码分析

前言 List、Set、HashMap作为Java中常用的集合&#xff0c;需要深入认识其原理和特性。 本篇博客介绍常见的关于Java中Set集合的面试问题&#xff0c;结合源码分析题目背后的知识点。 关于List的博客文章如下&#xff1a; Java进阶&#xff08;List&#xff09;——面试时L…

ssm+vue的孩童收养信息管理(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的孩童收养信息管理(有报告)。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring …

FPGA时序分析与约束(9)——主时钟约束

一、时序约束 时序引擎能够正确分析4种时序路径的前提是&#xff0c;用户已经进行了正确的时序约束。时序约束本质上就是告知时序引擎一些进行时序分析所必要的信息&#xff0c;这些信息只能由用户主动告知&#xff0c;时序引擎对有些信息可以自动推断&#xff0c;但是推断得到…