「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战」
前言
力扣第八十八题 合并两个有序数组 如下所示:
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意: 最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
示例 1:
输入: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
解释: 需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
一、思路
题目中有一个重要的提示信息:nums1 的初始长度为 m+n 这表示我们只需要将 nums2 中的 n 个元素插入其中即可。这也正符合题目中要求的,将修改的内容存储在 nums1 中。
这一题我是经过许多次 Debug 后才正确写出来的,所以同志们,碰到没通过的用例,调试才是唯一的真理啊。
因为要合并 nums1 和 nums2,我们可以用两个临时变量 n1 和 n2 表示我们当前取到了第几个元素了。在遍历的过程中只有出现 大于 的情况才需要将 nums1 的元素后移。
大致的步骤如下所示:
- 遍历整个
nums1 - 如果
nums1中的元素没有用完,且当前元素的值大于nums2的值时。我们将nums1剩余的元素后移一位,即nums[i, m]移动到nums[i+1, m+n2] - 遍历结束返回结果即可
举个例子
此处以示例中的 nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3 作为例子
- 遍历
nums1,当i = 0时,nums1[0] < nums2[1],将计数n1++, n1 = 1 - 当
i = 1时,nums1[1] == nums2[0],再将计数n1++, n1 = 2 - 当
i = 2时,nums1[2] > nums2[0],再nums1后面的元素后移一位,nums1变为了[1,2,3,3,0,0],再将nums2[0]插入到第2个位置,nums1变为了[1,2,2,3,0,0]。将计数n2++, n2 = 1 - 当
i = 3时,nums1[3] < nums2[1],再将计数n1++, n1 = 3 - 当
i = 4, 5时,nums1的元素用完了,故直接插入nums2的元素即可 - 返回最终的结果
[1, 2, 2, 3, 5, 6]即可
二、实现
实现代码
实现代码与思路中保持一致
public void merge(int[] nums1, int m, int[] nums2, int n) {
int n1 = 0, n2 = 0;
for (int i =0; i<nums1.length; i++) {
if (n1 >= m) { // nums1中的元素用完了
nums1[i] = nums2[n2];
n2++;
} else if (n2 < n && nums1[i] > nums2[n2]) { // 只有nums2中有元素,且当前元素大于才需要后移
// 从后向前,将nums1中的位置向后移动一个位置
for (int j=m+n2; j>i; j--) {
nums1[j] = nums1[j-1];
}
nums1[i] = nums2[n2];
n2++;
} else {
n1++;
}
}
}
测试代码
public static void main(String[] args) {
int[] nums1 = {1,2,3,0,0,0};
int[] nums2 = {2,5,6};
new Number88().merge(nums1, 3, nums2, 3);
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~