跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
|注册
博客列表

目录

  1. 一、题目描述
  2. 二、示例
  3. 示例 1
  4. 示例 2
  5. 示例 3
  6. 三、错误思路分析(为什么不能从前往后合并)
  7. 四、正确思路 —— 从后往前双指针(核心)
  8. 定义三个指针
  9. 处理逻辑
  10. 五、图解过程
  11. 六、C 语言实现
  12. 七、复杂度分析
  13. 八、边界情况分析(面试高频问)
  14. 情况 1:n = 0
  15. 情况 2:m = 0
  16. 情况 3:nums1 全部比 nums2 大
  17. 九、面试考点总结
  18. 十、延伸思考
  19. 十一、总结
C算法

LeetCode 88:合并两个有序数组(C 语言双指针详解)

本文讲解 LeetCode 88 题合并两个有序数组的解法。题目要求将 nums2 合并到 nums1 中并保持非递减顺序,且必须原地修改。核心思路是从后往前使用双指针遍历,比较两个数组末尾元素,将较大者放入 nums1 末尾,避免覆盖未处理数据。提供了 C 语言代码实现、图解过程及复杂度分析,并讨论了边界情况如 n=0 或 m=0 的处理。该方法时间复杂度为 O(m+n),空间复杂度为 O(1)。

晚风告白发布于 2026/3/290 浏览

一、题目描述

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,以及两个整数 m 和 n。

  • nums1 的长度为 m + n
  • 前 m 个元素为有效元素
  • 后 n 个元素为 0(占位)
  • nums2 长度为 n

要求: 将 nums2 合并到 nums1 中,使结果仍然保持非递减顺序。

注意: 必须 原地修改 nums1,不能返回新数组。


二、示例

示例 1

输入: nums1 = [1,2,3,0,0,0], m = 3 nums2 = [2,5,6], n = 3

输出: [1,2,2,3,5,6]

示例 2

输入: nums1 = [1], m = 1 nums2 = [], n = 0

输出: [1]

示例 3

输入: nums1 = [0], m = 0 nums2 = [1], n = 1

输出: [1]


三、错误思路分析(为什么不能从前往后合并)

很多人第一反应:

从前往后比较,小的放前面。

问题是:

  • nums1 前面是有效数据
  • 后面是 0 占位
  • 如果从前往后插入,会覆盖还未比较的数据

举例:

nums1 = [1,2,3,0,0,0] nums2 = [2,5,6]

如果从前面开始插入,后面的 3 可能会被覆盖。


四、正确思路 —— 从后往前双指针(核心)

关键思想:

既然后面有空位,那就从后往前填!

定义三个指针

i = m - 1 // nums1 有效元素最后一个 j = n - 1 // nums2 最后一个 k = m + n - 1 // nums1 总数组最后一个位置

处理逻辑

  1. 比较 nums1[i] 和 nums2[j]
  2. 较大的放到 nums1[k]
  3. 指针向前移动
  4. 重复直到 nums2 用完

五、图解过程

示例:

nums1 = [1,2,3,0,0,0] nums2 = [2,5,6]

初始:

i -> 3 j -> 6 k -> 最后位置

步骤:

比较放入数组变成
3 vs 66[1,2,3,0,0,6]
3 vs 55[1,2,3,0,5,6]
3 vs 23[1,2,3,3,5,6]
2 vs 22[1,2,2,3,5,6]
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog

更多推荐文章

查看全部

暂无推荐文章,稍后可再来查看。

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown 转 HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online

  • HTML 转 Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

完成。


六、C 语言实现

void merge(int* nums1, int nums1Size, int m,
           int* nums2, int nums2Size, int n) {
    
    int i = m - 1;          // nums1 有效部分末尾
    int j = n - 1;          // nums2 末尾
    int k = m + n - 1;      // nums1 总末尾
    
    // 从后往前合并
    while (i >= 0 && j >= 0) {
        if (nums1[i] > nums2[j]) {
            nums1[k--] = nums1[i--];
        } else {
            nums1[k--] = nums2[j--];
        }
    }
    
    // 如果 nums2 还有剩余
    while (j >= 0) {
        nums1[k--] = nums2[j--];
    }
}

七、复杂度分析

项目复杂度
时间复杂度O(m + n)
空间复杂度O(1)
  • 每个元素只遍历一次
  • 没有额外数组
  • 原地修改

八、边界情况分析(面试高频问)

情况 1:n = 0

nums2 为空

直接返回即可,不会进入循环。

情况 2:m = 0

nums1 没有有效元素

直接把 nums2 拷贝过去。

情况 3:nums1 全部比 nums2 大

仍然能正常处理。


九、面试考点总结

这题是经典基础题,但面试官爱问:

  • 为什么要从后往前?
  • 能不能 O(1) 空间?
  • 如果允许额外数组呢?
  • 如果是链表呢?

本质考察:

  • 双指针
  • 原地合并
  • 逆向思维
  • 边界处理

十、延伸思考

如果改成:

合并两个有序链表?

那就变成经典链表双指针题。

如果改成:

合并 K 个有序数组?

那就需要优先队列(小顶堆)。


十一、总结

本题核心只有一句话:

有空位在后面,就从后面往前填。

这是一个基础题,属于:

  • 双指针入门
  • 面试高频
  • LeetCode 150 系列