双指针
为了合并两个已排序的数组 nums1
和 nums2
,并将结果存储在 nums1
中,我们可以采用双指针的方式从后向前进行合并。这种方法的好处是可以避免在nums1
中移动元素,从而提高效率。
算法步骤
-
初始化三个指针:
p1
指向nums1
的有效部分的最后一个元素,即m - 1
。p2
指向nums2
的最后一个元素,即n - 1
。p
指向nums1
的最后一个位置,即m + n - 1
。
-
从后向前遍历数组:
- 比较
nums1[p1]
和nums2[p2]
:- 如果
nums1[p1] > nums2[p2]
,将nums1[p1]
赋值给nums1[p]
,并将p1
和p
向前移动一位。 - 否则,将
nums2[p2]
赋值给nums1[p]
,并将p2
和p
向前移动一位。
- 如果
- 比较
-
如果
nums2
中还有剩余元素(即p2
>= 0),将这些元素复制到nums1
的前面。
代码实现
java
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
// corner case
// core
int p1 = m - 1, p2 = n - 1, p = m + n - 1;
while (p1 >= 0 && p2 >= 0) {
if (nums1[p1] > nums2[p2]) {
nums1[p--] = nums1[p1--];
} else {
nums1[p--] = nums2[p2--];
}
}
while (p2 >= 0) {
nums1[p--] = nums2[p2--];
}
}
}
python
def merge(nums1, m, nums2, n):
# 设置指针
p1, p2, p = m - 1, n - 1, m + n - 1
# 从后向前合并
while p1 >= 0 and p2 >= 0:
if nums1[p1] > nums2[p2]:
nums1[p] = nums1[p1]
p1 -= 1
else:
nums1[p] = nums2[p2]
p2 -= 1
p -= 1
# 如果 nums2 还有剩余元素,直接复制到 nums1
# 如果 nums1 还有剩余元素,不需要处理,因为它们已经在正确的位置
nums1[:p2 + 1] = nums2[:p2 + 1]
# 示例用法
nums1 = [1, 2, 3, 0, 0, 0]
m = 3
nums2 = [2, 5, 6]
n = 3
merge(nums1, m, nums2, n)
print(nums1) # 输出: [1, 2, 2, 3, 5, 6]
复杂度分析
- 时间复杂度 :O(m + n),因为我们最多需要遍历
nums1
和nums2
各一次。 - 空间复杂度 :O(1),因为我们是直接在
nums1
上进行修改,没有使用额外的空间。