02-合并两个有序数组

embedded/2025/2/7 13:48:53/

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

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

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

方法一

function merge(nums1: number[], m: number, nums2: number[], n: number): void {// 从后往前比较两个数组的元素,将较大的元素放到 nums1 的末尾let p1 = m - 1; // nums1 中有效元素的最后一个索引let p2 = n - 1; // nums2 中最后一个元素的索引let p = m + n - 1; // nums1 合并后数组的最后一个索引while (p1 >= 0 && p2 >= 0) {if (nums1[p1] > nums2[p2]) {nums1[p] = nums1[p1];p1--;} else {nums1[p] = nums2[p2];p2--;}p--;}// 如果 nums2 中还有剩余元素,将其依次复制到 nums1 的前面while (p2 >= 0) {nums1[p] = nums2[p2];p2--;p--;}
}// 示例调用
const nums1 = [1, 2, 3, 0, 0, 0];
const m = 3;
const nums2 = [2, 5, 6];
const n = 3;
merge(nums1, m, nums2, n);
console.log(nums1); 

代码解释

  1. 初始化指针

    • p1 指向 nums1 中有效元素的最后一个位置(索引为 m - 1)。
    • p2 指向 nums2 中最后一个元素的位置(索引为 n - 1)。
    • p 指向 nums1 合并后数组的最后一个位置(索引为 m + n - 1)。
  2. 从后往前比较并填充

    • 使用 while 循环,只要 p1 和 p2 都大于等于 0,就比较 nums1[p1] 和 nums2[p2] 的大小。
    • 如果 nums1[p1] 大于 nums2[p2],将 nums1[p1] 放到 nums1[p] 的位置,并将 p1 减 1;否则将 nums2[p2] 放到 nums1[p] 的位置,并将 p2 减 1。
    • 每次放置元素后,将 p 减 1。
  3. 处理剩余元素

    • 当 p1 小于 0 时,说明 nums1 中的有效元素已经全部处理完,而 nums2 中可能还有剩余元素。
    • 使用另一个 while 循环,将 nums2 中剩余的元素依次复制到 nums1 的前面。

复杂度分析

  • 时间复杂度:,因为只需要遍历两个数组一次。
  • 空间复杂度:,只使用了常数级的额外空间。

方法二 

function merge(nums1: number[], m: number, nums2: number[], n: number): void {// 正确截取数组let arr1 = nums1.slice(0, m);let arr2 = nums2.slice(0, n);// 合并数组let arr3 = arr1.concat(arr2);// 对合并后的数组进行排序arr3.sort((a, b) => a - b);// 将排序后的数组元素复制回 nums1for (let i = 0; i < arr3.length; i++) {nums1[i] = arr3[i];}
}// 示例调用
const nums1 = [1, 2, 3, 0, 0, 0];
const m = 3;
const nums2 = [2, 5, 6];
const n = 3;
merge(nums1, m, nums2, n);
console.log(nums1);

代码解释

  1. 数组截取
    • let arr1 = nums1.slice(0, m); 从 nums1 里截取前 m 个有效元素。
    • let arr2 = nums2.slice(0, n); 从 nums2 里截取所有 n 个元素。
  2. 合并数组
    • let arr3 = arr1.concat(arr2); 把 arr1 和 arr2 合并成新数组 arr3
  3. 数组排序
    • arr3.sort((a, b) => a - b); 对合并后的数组 arr3 进行排序,保证元素是非递减顺序。
  4. 复制回 nums1
    • 用 for 循环把排序后的 arr3 里的元素逐个复制到 nums1 中。

复杂度分析

  • 时间复杂度:主要是排序操作的复杂度,JavaScript 的 sort 方法平均时间复杂度是 ,因为合并后的数组长度是 m + n
  • 空间复杂度:,因为额外创建了一个长度为 m + n 的数组 arr3 来存储合并后的元素。

这种方法虽然实现了功能,但相比从后往前双指针的方法(时间复杂度 ,空间复杂度 ),在性能上会差一些。


http://www.ppmy.cn/embedded/160314.html

相关文章

实现一个 LRU 风格的缓存类

实现一个缓存类 需求描述豆包解决思路&#xff1a;实现代码&#xff1a;优化11. std::list::remove 的时间复杂度问题2. 代码复用优化后的代码优化说明 优化21. 边界条件检查2. 异常处理3. 代码封装性4. 线程安全优化后的代码示例优化说明 DeepSeek&#xff08;深度思考R1&…

2023年总结感悟

农民用铁锹挖土&#xff0c;和工程师用电流表测试电流其实是一样的。肌肉力量是男孩信息的源泉74岁时一个门槛&#xff0c;老人看一面就少看一面对于老人来说可以自己吃饭&#xff0c;自己走路已经很不错了&#xff0c;若是由于疾病预后很差&#xff0c;不如有尊严的离开世界护…

HarmonyOS:给您的应用添加通知

一、通知介绍 通知旨在让用户以合适的方式及时获得有用的新消息&#xff0c;帮助用户高效地处理任务。应用可以通过通知接口发送通知消息&#xff0c;用户可以通过通知栏查看通知内容&#xff0c;也可以点击通知来打开应用&#xff0c;通知主要有以下使用场景&#xff1a; 显示…

【Redis】主从模式,哨兵,集群

主从复制 单点问题&#xff1a; 在分布式系统中&#xff0c;如果某个服务器程序&#xff0c;只有一个节点&#xff08;也就是一个物理服务器&#xff09;来部署这个服务器程序的话&#xff0c;那么可能会出现以下问题&#xff1a; 1.可用性问题&#xff1a;如果这个机器挂了…

C语言switch case语句详解(非常详细)

在C语言中&#xff0c;switch case 语句是一种多分支选择结构&#xff0c;用于根据变量的值执行不同的代码块。 相比于if else语句&#xff0c;switch case在处理多个固定值的条件判断时更加简洁和高效。本文将详细讲解switch case语句的用法、语法格式、实例代码、注意事项&a…

Hive修复分区

Hive修复分区 简介 Hive的MSCK REPAIR TABLE命令用于修复&#xff08;即添加丢失的&#xff09;表分区。通常用于那些已在HDFS中存在&#xff0c;但尚未在Hive元数据中注册的分区。 当你在HDFS文件系统中手动添加或删除分区目录&#xff0c;Hive并不会自动识别这些更改。为同步…

网络安全——Span 安全监控

SPAN释义&#xff1a; SPAN技术我们可以把交换机上某些想要被监控端口&#xff08;以下简称受控端口&#xff09;的数据流COPY或MIRROR一 份&#xff0c;发送给连接在监控端口上的流量分析仪&#xff0c;比如CISCO的IDS或是装SNIFFE工具的PC受控端口和 监控端口可以在同一台交…

(2024|Nature Medicine,生物医学 AI,BiomedGPT)面向多种生物医学任务的通用视觉-语言基础模型

BiomedGPT: A generalist vision–language foundation model for diverse biomedical tasks 目录 1. 摘要 2. 引言 3. 相关研究 3.1 基础模型与通用生物医学 AI 3.2 生物医学 AI 的局限性 3.3 BiomedGPT 的创新点 4. 方法 4.1 架构及表示 4.1.1 模型架构选择 4.1.2 …