两个非递减有序顺序表合并成新有序顺序表(O (n+m))知识点精讲

核心考点:顺序表 + 二路归并(双指针),是数据结构线性表经典基础题。

一、基础概念

1. 顺序表

顺序表:用一段连续的内存空间存储数据元素,也就是 C 语言里的数组。
特点:

  • 随机访问快:a[i] 直接取元素,(O(1))
  • 插入 / 删除慢:中间增删需要移动后面大量元素,(O(n))
  • 本题输入就是两个顺序表,输出也是新顺序表

非递减有序:后面元素 ≥ 前面元素,允许相等,如 1,2,2,3,5

2. 题目要求解读

时间复杂度 (O(n+m))

  • n:第一个表长度,m:第二个表长度
  • 含义:最多只扫描两个数组一遍,每个元素只处理一次
    ❌ 禁止做法:合并后再排序(复杂度 (O((n+m)\log(n+m))),不满足);逐个插入((O(nm)))

二、核心算法:二路归并(双指针法)

思想

两个已经有序的序列,同时从头部开始扫描,每次取两个指针指向元素里更小的那个放到新表。

  1. 指针 i:顺序表 A 当前位置,初始 i=0
  2. 指针 j:顺序表 B 当前位置,初始 j=0
  3. 指针 k:新顺序表存放位置,初始 k=0

循环条件:i < n && j < m(两个表都还有元素没读完)

  • 如果 A[i] <= B[j]:把 A [i] 放进新表,i++,k++
  • 否则:把 B [j] 放进新表,j++,k++

当其中一个表读完,剩下另一个表的剩余元素直接全部追加(本身有序,不用比较)。

复杂度分析

  • 时间 (O(n+m)):i 最多走 n 次,j 最多走 m 次,所有循环加起来一共 (n+m) 次操作
  • 空间 (O(n+m)):需要开辟新顺序表存放结果(题目要求生成新顺序表,不能原地覆盖原表)

二路归并也是归并排序里面最核心的子过程!归并排序就是不断拆分,最后靠二路归并合并有序子数组。


三、相关知识点拓展(容易混淆)

1. 顺序表 vs 链表的合并区别

  • 本题:顺序表合并,需要开新数组存结果,连续空间。
  • 如果是有序单链表合并:不需要开辟新节点,只修改指针链接,额外空间(O(1))。

2. 原地合并(倒序双指针)

如果题目改成:第一个数组 A 后面预留足够空间,直接把 B 合并进 A,不开新数组。
思路:从两个数组末尾最大值开始向前比较,大的放到 A 尾部空位。

  • 时间依然 (O(n+m)),额外空间(O(1))
    ⚠️ 注意:本题不适用,本题明确生成一个新顺序表,所以用正向双指针即可。

3. 为什么不能直接拼接后排序?

拼接再排序虽然代码简单,但没有利用 “原数组已经有序” 这个条件,时间复杂度变成 (O((n+m)\log(n+m))),无法满足题目的复杂度要求,考试会扣分。

4. 插入法为什么不行(逐个插入)

拿一个表作为基础,另一个表元素逐个查找位置插入。
顺序表插入需要大量元素后移,最坏情况 (O(n\times m)),效率极低,不符合(O(n+m))要求。


四、考点总结(考试简答题常考)

  1. 顺序表的存储特点:连续内存,随机访问,插入删除代价高
  2. 二路归并算法原理:双指针,依次选取较小元素,剩余元素直接追加
  3. 复杂度计算:时间(O(n+m)),空间(O(n+m))
  4. 算法前提:两个输入序列本身已经有序,二路归并才能达到线性时间
  5. 边界情况(写代码必须考虑)
    • 其中一个顺序表为空(n=0 或者 m=0),直接复制另一个表
    • 存在重复元素(非递减,<= 不能写成<,否则丢元素)
    • 一个表全部元素都小于另一个表

边界测试案例

例 1:其中一个为空
输入:

0 3
(空行)
2 4 6

输出:长度 3,2 4 6

例 2:存在重复元素

3 3
1 2 2
2 3 4

合并结果:1 2 2 2 3 4


五、常见易错点

  1. 条件写成 A[i] < B[j] 而不是 <= → 重复元素会丢失或者顺序错误
  2. 忘记处理剩余元素循环,只执行第一个 while,数组后面元素丢了
  3. 数组开太小,数组越界
  4. 复杂度分析错误,以为拼接排序是 O (n+m)

posted on 2026-10-27 16:07  谢天佑  阅读(8)  评论(0)    收藏  举报