当前位置: 首页 > news >正文

LeetCode CodeTop 88.合并两个有序数组

思路:

1.错误思路:如果从左往右地把nums2合并到nums1中,假设nums2[0] < nums1[0],那么nums2[0]会直接覆盖掉nums1[0],这不是我们期望看到的。

2.正确思路:从右往左地把nums2合并到nums1中,举例如下:

(1)nums1 = [1,2,3,*,*,*],nums2 = [4,5,6]。这里我用 * 表示可以填入的空位。在这个例子中,nums2可以直接填入nums1后面的3个空位,得到[1,2,3,4,5,6],没有任何错误覆盖。

(2)nums1 = [1,2,6,*,*,*],nums2 = [3,4,5]。这里nums1中的6是最大的,应当填入末尾。现在nums1 = [1,2,*,*,*,6],注意nums2现在这个位置空出了。然后把nums2中的数字填入空位,得到[1,2,3,4,5,6],没有任何错误覆盖。

(3)上面的例子表明,把nums1中的数字移到另一个空位上,又产生了一个新的空位,所以剩余空位的个数是不变的,我们总是有空位可以让nums2的数字填入,不会发生错误覆盖,这是如下算法正确的前提。

3.算法:

(1)初始化3个指针,p1 = m - 1指向nums1的末尾,p2 = n - 1指向nums2的末尾,p = m + n - 1指向合并后的数组末尾

(2)不断比较nums1[p1]和nums2[p2]的大小,将较大的值放入nums1[p]。如果p1 >= 0且nums1[p1]更大,那么放入后p1和p减1,否则p2和p减1。注意nums1[p1] == nums2[p2]时放入谁都可以,不妨规定放入nums2[p2],这样在数组元素都相等的情况下,只需要把nums2的数据填入nums1中,效率更高。

(3)循环直到p2 < 0,此时nums2的所有元素均已填入nums1。你可能会想,如果nums1还有元素没有移动呢?注意到当nums2都合并到nums1中时,nums1剩余未移动的元素,它要移动的目标位置就是它自己所处的位置,所以无需移动,合并完毕。这可以算作一个小优化,比如nums1 = [1,2,3,*,*,*],nums2 = [4,5,6],其实只要把nums2的所有数都填入nums1中,合并就已经结束了,即便此时p1 = 2仍然 >= 0。

4.复杂度分析:

(1)时间复杂度:O(m + n),最坏情况下如nums1​=[4,5,6,∗,∗,∗],nums2​=[1,2,3],每个数都需要移动一次。

(2)空间复杂度:O(1)。

附代码:

class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int p1 = m - 1; int p2 = n - 1; int p = m + n - 1; // 说明nums2还有要合并的元素 while(p2 >= 0){ // 如果p1 < 0,那么走else分支,把nums2合并到nums1中 if(p1 >= 0 && nums1[p1] > nums2[p2]){ // 填入nums1[p1] nums1[p--] = nums1[p1--]; }else{ // 填入nums2[p2] nums1[p--] = nums2[p2--]; } } } }

ACM模式:

import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // 读取 m 和 n int m = scanner.nextInt(); int n = scanner.nextInt(); // 读取 nums1 的前 m 个有效元素,后面 n 个位置为 0 int[] nums1 = new int[m + n]; for (int i = 0; i < m; i++) { nums1[i] = scanner.nextInt(); } // nums1 剩余的位置默认为 0,不需要读取 // 读取 nums2 的 n 个元素 int[] nums2 = new int[n]; for (int i = 0; i < n; i++) { nums2[i] = scanner.nextInt(); } // 调用合并方法 Solution solution = new Solution(); solution.merge(nums1, m, nums2, n); // 输出合并后的 nums1 for (int i = 0; i < m + n; i++) { System.out.print(nums1[i]); if (i < m + n - 1) { System.out.print(" "); } } System.out.println(); scanner.close(); } } class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int p1 = m - 1; int p2 = n - 1; int p = m + n - 1; // 说明 nums2 还有要合并的元素 while (p2 >= 0) { // 如果 p1 < 0,那么走 else 分支,把 nums2 合并到 nums1 中 if (p1 >= 0 && nums1[p1] > nums2[p2]) { // 填入 nums1[p1] nums1[p--] = nums1[p1--]; } else { // 填入 nums2[p2] nums1[p--] = nums2[p2--]; } } } }

构造测试用例:

import java.util.*; class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int p1 = m - 1; int p2 = n - 1; int p = m + n - 1; // 说明 nums2 还有要合并的元素 while (p2 >= 0) { // 如果 p1 < 0,那么走 else 分支,把 nums2 合并到 nums1 中 if (p1 >= 0 && nums1[p1] > nums2[p2]) { // 填入 nums1[p1] nums1[p--] = nums1[p1--]; } else { // 填入 nums2[p2] nums1[p--] = nums2[p2--]; } } } } public class Main { public static void main(String[] args) { Solution solution = new Solution(); // 测试用例1:基本合并(两个数组都有元素) System.out.println("测试用例1 - 基本合并"); int[] nums1_1 = {1, 2, 3, 0, 0, 0}; int m1 = 3; int[] nums2_1 = {2, 5, 6}; int n1 = 3; System.out.print("nums1原始: "); System.out.print(Arrays.toString(nums1_1)); System.out.print("nums2: "); System.out.print(Arrays.toString(nums2_1)); solution.merge(nums1_1, m1, nums2_1, n1); System.out.print("合并后: "); System.out.print(Arrays.toString(nums1_1)); System.out.println("期望: [1, 2, 2, 3, 5, 6]"); System.out.println(); } }
http://www.gsyq.cn/news/1505726.html

相关文章:

  • 天津红桥防水补漏哪家靠谱?2026正规修缮公司排名实测(全区通用) - 苏易房屋修缮
  • 2026北京朝阳区宝格丽首饰回收:这些细节决定回收价 - 逸程
  • 如何高效使用downkyi哔哩下载姬:B站8K超高清视频下载终极指南
  • 告别卡顿与延迟:用Sunshine构建你的家庭游戏串流中心
  • 【趣解】COM/DCOM/COM+:微软的构件“三国演义“
  • DDrawCompat:为Windows Vista-11系统重燃经典DirectX游戏生命力的终极兼容方案
  • STM32F411RC平台RT-Thread下开箱即用的片内Flash分区管理工程
  • 卫生间漏水到楼下怎么查找漏水点?2026开封24小时上门维修电话TOP7机构推荐,免费勘察+精准定位,专业师傅处理屋顶墙体洗手间暗管漏水 - 一休咨询
  • Spotlight 2 上市售价 129.99 美元,呼吸练习与聚光功能助演讲者从容展示!
  • IPv4与IPv6协议详解:起源、应用、优缺点及未来发展
  • 题解:学而思编程 动态绝对值最小
  • 从零到一:用Charles打通移动端调试全链路,H5/APP抓包实战
  • 降AIGC黑科技!AI率92%暴降至5%!实测10款AI智能降重工具!免费额度狂薅攻略
  • 亚马逊公开商品页批量抓取与结构化导出工具(Python+Selenium)
  • 探索AnimateAnyone:让静态图像“动起来“的AI动画生成方案
  • Linux 基金会启动 OpenSharing 项目,为 AI 资产和数据交换立标准
  • 2026年安徽省六安不用局限本地职校,合肥省属公办对外地生源免学费招录 - cc江江
  • 神经符号AI破局关键:深入浅出了解描述逻辑DL
  • 终于找到!青岛无外包、自有团队的良心防水公司!李沧防水/城阳防水/即墨防水/胶南防水都有团队 - 青岛防水品牌推荐
  • 本文揭示了字节跳动多个冷门业务板块(如动态壁纸、宠物服务、垂钓、手工DIY等)实际依托阿里云存储与计算服务的现象。通过列举60项细分业务,详细披露了各类用户数据(图片、视频、音频、文档)及业务系统(数
  • 深入解析80C51 OTP/ROM编程与安全机制:从EPROM原理到量产实战
  • 2026南京全域黄金回收排行|收的顶合规透明报价优厚专业稳妥 - 奢侈品回收评测
  • MSC8254 DSP硬件设计:DDR与SerDes接口AC时序规范深度解析与实践指南
  • 南京本地黄金回收避坑指南:知道这三步,轻松多回收几百上千元 - 奢侈品回收评测
  • 020华夏之光永存,助力国家科技破局:移动端与服务器端高端CPU/GPU底层IP核架构工程落地终版(全专家闭环强化版)
  • 卫生间漏水到楼下怎么查找漏水点?2026黄石24小时上门维修电话TOP7机构推荐,免费勘察+精准定位,专业师傅处理屋顶墙体洗手间暗管漏水 - 一休咨询
  • 2026常州包包回收选购指南:5家高分实体店推荐 - 奢侈品交易观察员
  • 彻底改变你的macOS观影体验:IINA播放器深度解析
  • 咸鱼淘来的SES 2.66寸墨水屏,用MicroPython驱动显示中文踩坑全记录(附完整代码)
  • 2026成都劳力士、 欧米茄 、百达翡丽 、积家等手表回收性价比测评:添价收黄金奢侈品回收中心专业之选 - 薛定谔的梨花猫