合并有序数组
使用双指针合并两个有序数组
问题
给定两个按升序排列的数组,将它们合并为一个有序数组。
解答
方法一:双指针
function mergeSortedArrays(arr1, arr2) {
const result = [];
let i = 0; // arr1 指针
let j = 0; // arr2 指针
// 比较两个数组的元素,较小的放入结果
while (i < arr1.length && j < arr2.length) {
if (arr1[i] <= arr2[j]) {
result.push(arr1[i]);
i++;
} else {
result.push(arr2[j]);
j++;
}
}
// 处理剩余元素
while (i < arr1.length) {
result.push(arr1[i]);
i++;
}
while (j < arr2.length) {
result.push(arr2[j]);
j++;
}
return result;
}
// 测试
console.log(mergeSortedArrays([1, 3, 5], [2, 4, 6])); // [1, 2, 3, 4, 5, 6]
console.log(mergeSortedArrays([1, 2, 3], [4, 5])); // [1, 2, 3, 4, 5]
console.log(mergeSortedArrays([], [1, 2])); // [1, 2]
方法二:原地合并(LeetCode 88)
当第一个数组有足够空间时,从后往前合并,避免元素覆盖。
function merge(nums1, m, nums2, n) {
let p1 = m - 1; // nums1 有效元素的末尾
let p2 = n - 1; // nums2 末尾
let p = m + n - 1; // 合并后数组的末尾
// 从后往前填充
while (p2 >= 0) {
if (p1 >= 0 && nums1[p1] > nums2[p2]) {
nums1[p] = nums1[p1];
p1--;
} else {
nums1[p] = nums2[p2];
p2--;
}
p--;
}
return nums1;
}
// 测试:nums1 长度为 m + n,后面用 0 占位
const nums1 = [1, 2, 3, 0, 0, 0];
merge(nums1, 3, [2, 5, 6], 3);
console.log(nums1); // [1, 2, 2, 3, 5, 6]
方法三:简洁写法
function mergeSortedArrays(arr1, arr2) {
const result = [];
let i = 0, j = 0;
while (i < arr1.length || j < arr2.length) {
if (j >= arr2.length || (i < arr1.length && arr1[i] <= arr2[j])) {
result.push(arr1[i++]);
} else {
result.push(arr2[j++]);
}
}
return result;
}
关键点
- 双指针法时间复杂度 O(m+n),空间复杂度 O(m+n)
- 原地合并从后往前,避免覆盖未处理的元素
- 循环结束后要处理剩余元素
- 注意边界条件:空数组、长度不等的数组
目录