LeetCode 88. 合并两个有序数组 | 新手从零刷题全过程(超详细踩坑记录)
一、题目描述
给你两个非递减有序的整数数组 nums1、nums2,以及 m、n。
m:nums1 的有效元素个数n:nums2 的有效元素个数- nums1 长度为
m+n,后面n个 0 为占位空间
要求:原地合并到 nums1 中,不返回新数组,最终保持升序。
二、解题思路总览
本题我使用了两种解法:
- 暴力法:先合并 + 整体排序(新手入门最快)
- 最优解法:逆向双指针(面试标准最优解)
我全程记录了新手所有真实踩坑,非常适合零基础算法入门。
方法一:暴力解法(先合并后排序)
1. 解题思路
我首先没有考虑到使用集合中原本存在的顺序,选择直接把nums2的数据插入到nums1中了
- 将
nums2所有元素复制到nums1尾部空位 - 直接对 nums1 整体排序
- 原地修改,无需新开数组
2. 我新手踩坑记录
- 错误:循环条件写成
i < m - 正确:必须
i < n - 原因:n=0 时如果继续循环,会数组越界
3. AC 代码
import java.util.Arrays;
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
// 将nums2全部复制到nums1尾部
for(int i = 0; i < n; i++){
nums1[m + i] = nums2[i];
}
// 整体排序
Arrays.sort(nums1);
}
}
4. 复杂度分析
时间复杂度:(O((m+n)\log(m+n)))
空间复杂度:(O(1))
5. 优缺点
优点:逻辑最简单、不容易写错、快速过题
缺点:没有利用数组已有序的条件,效率差,面试不推荐
方法二:最优解法|逆向双指针(核心重点)
1. 为什么要从后往前?
正序合并会覆盖 nums1 未读取的有效数据
nums1 尾部有空位,从后往前填不会覆盖数据
2. 指针定义
p1:nums1 有效元素末尾 m-1
p2:nums2 末尾 n-1
p3:nums1 最终填充位置末尾 m+n-1
3. 算法流程
两个数组都有值时,谁大谁放最后
对应指针前移,填充指针一定前移
遍历结束后,如果 nums2 还有剩余小数,全部拷贝到前面
4. 我刷题全程真实踩坑(新手必看)
坑 1:Java/Python 语法混淆
错误:p1>=0 and p2>=0
正确:p1 >= 0 && p2 >= 0
坑 2:赋值符号与判断符号混淆
错误:if(nums1[p1] = nums2[p2])
正确:if(nums1[p1] == nums2[p2])
坑 3:相等时同时移动两个指针(致命 BUG)
错误:相等时 p1–、p2-- 一起移动
后果:跳过数据、数组顺序错乱
坑 4:忘记移动填充指针 p3
后果:数据反复覆盖同一个位置
坑 5:缺少第二段 while
后果:nums1 提前遍历完、nums2 剩余负数 / 小数无法合并
5. 最终完整 AC 代码
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int p1 = m - 1;
int p2 = n - 1;
int p3 = m + n - 1;
// 双数组同时遍历,从后往前取大数
while(p1 >= 0 && p2 >= 0){
if(nums1[p1] > nums2[p2]){
nums1[p3] = nums1[p1];
p1--;
}else{
nums1[p3] = nums2[p2];
p2--;
}
p3--;
}
// 处理nums2剩余元素(关键边界)
while(p2 >= 0){
nums1[p3] = nums2[p2];
p2--;
p3--;
}
}
}
6. 复杂度分析
时间复杂度:(O(m+n)) 线性遍历,最优解
空间复杂度:(O(1)) 原地操作
7. 全部边界覆盖
n = 0:nums2 为空,直接返回
m = 0:直接复制 nums2 全部数据
存在相同元素、存在负数全部通过

550

被折叠的 条评论
为什么被折叠?



