思路
使用逆向双指针。因为数组1最后的几位是为了放置最终结果元素的,所以初始值是无效的,我们可以直接将最终元素值从尾巴开始放入,而不需要考虑数据被覆盖(保存原值)的问题,因此称为“逆向”。然后还需要一个指针(数组1指针)记录还未放好位置的数组1下标,另一个指针(数组2指针)记录还未放好位置的数组2下标,此处称为“双指针”。尾指针指向的值为数组1指针所在元素和数组2指针两者中的最大值,尾指针在每次循环时前移1位
解题过程
前提条件:两个数组的元素都是有序递增的,可能出现的情况:
- 数组2为空,直接返回即可
- 数组1指针和数组2指针都可能已经指向-1下标,等于-1时,即该数组元素合并好,此时只需要移动另外一个指针(不等于-1的)的元素即可
- 尾指针每赋值一次后,则往前移1位,相应的最大值所在的指针也要前移1位
代码
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int tail = m + n - 1;
int p1 = m - 1, p2 = n - 1;
// 数组2为空的情况, 直接就是完成的数据
if (n == 0) {
return;
}
// 只要数组1指针和数组2指针有一个没到首位, 都继续执行循环
while (p1 >= 0 || p2 >= 0) {
if (p1 == -1) {
// 数组1为空, 或者数组1的元素已经全部移动完的情况
nums1[tail] = nums2[p2];
p2--;
} else if (p2 == -1) {
// 数组2的元素已经全部移动到nums1的情况
nums1[tail] = nums1[p1];
p1--;
} else if (nums2[p2] > nums1[p1]) {
// 数组2元素比数组1元素大的时候
nums1[tail] = nums2[p2];
p2--;
} else {
// 数组2元素小于等于数组1元素的时候
nums1[tail] = nums1[p1];
p1--;
}
// 每遍历一次, 末尾值就能找到1位, 所以尾指针要往左移1位
tail--;
}
}
}