LeetCode 88题要求原地合并两个有序数组,必须从后往前双指针归并:因nums1后n位为空闲空间,从前向后会覆盖未处理元素;而从k=m+n−1开始填最大值,可避免读写冲突,实现O(m+n)时间、O(1)空间。

PHP 7.3 中实现“合并两个有序数组”这道题,核心不是简单拼接,而是利用已有序特性做 原地归并,时间复杂度 O(m+n),空间复杂度 O(1)。它和 LeetCode 88 题逻辑一致:给定数组 nums1(长度为 m+n,后 n 位为占位 0),nums2(长度为 n),要求将 nums2 合并入 nums1 并保持非递减顺序。
为什么必须从后往前合并?
因为 nums1 的有效数据只占前 m 位,后 n 位是空闲空间。若从前向后归并,可能覆盖 nums1 中尚未处理的元素;而从后往前,每次把当前最大值放到 nums1[k](k 从 m+n−1 开始递减),完全避开读写冲突。
- 指针
i = m − 1指向nums1最后一个有效数 - 指针
j = n − 1指向nums2最后一个数 - 指针
k = m + n − 1指向nums1合并后末尾位置
完整 PHP 7.3 兼容实现
以下代码严格遵循原地、无额外数组、兼容空输入(m=0 或 n=0):
function merge(&$nums1, int $m, array $nums2, int $n): void
{
$i = $m - 1;
$j = $n - 1;
$k = $m + $n - 1;
<pre class="brush:php;toolbar:false;">// 双指针从后往前比较,填入 nums1[k]
while ($i >= 0 && $j >= 0) {
if ($nums1[$i] > $nums2[$j]) {
$nums1[$k--] = $nums1[$i--];
} else {
$nums1[$k--] = $nums2[$j--];
}
}
// 若 nums2 还剩元素(nums1 已耗尽),全部拷入 nums1 前部
while ($j >= 0) {
$nums1[$k--] = $nums2[$j--];
}
// 若 nums1 还剩元素,无需操作——它们已在正确位置}
注:PHP 7.3 支持严格类型声明(如 int $m),函数签名中使用 &$nums1 确保原地修改生效。
常见错误与边界验证
这段代码能稳健应对所有边界情况:
-
m = 0:$nums1 全是占位 0,循环跳过第一阶段,直接执行
while($j>=0),把 $nums2 全拷入 - n = 0:$nums2 为空,整个 while 循环不进,$nums1 不变,符合预期
-
含重复值:题目要求“非递减”,相等时优先取 $nums2(因条件是
的反向逻辑),不影响正确性 - 数值键安全:PHP 数组下标为整型,$nums1 和 $nums2 均按索引数组使用,无键名干扰
对比 array_merge() 为何不可行?
虽然 array_merge($nums1, $nums2) 看似一行解决,但它:
- 会创建新数组,违反“原地合并”要求
- 对数字键强制重编号(如 [0,1,2] + [0,1] → [0,1,2,0,1]),破坏原始位置语义
- 无法复用 $nums1 后段空间,空间复杂度升至 O(m+n)
- 未利用“两数组已排序”这一关键信息,失去算法意义
这道题考的是归并思想与指针控制能力,不是语言内置函数调用技巧。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











