给你两个有序整数数组nums1 和 nums2,请你将 nums2 合并到nums1中,使 nums1 成为一个有序数组。 初始化nums1 和 nums2 的元素数量分别为m 和 n 。你可以假设nums1 的空间大小等于m + n,这样它就有足够的空间保存来自 nums2 的元素。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
提示:
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-109 <= nums1[i], nums2[i] <= 109
来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/merge-sorted-array
#解法 该题有多种解法,朴素解法是先将两个数组合并,然后再进行排序。但是题目给出的数组已经是有序的了,要充分利用该信息。 如果从有序的数组的头部每次取出一个元素进行比较,选取较小的那个,那么选取判断后弹出的数据将会是数组1和数组2合并后的结果。因此需要建立辅助空间来存储选取后弹出的结果。 该空间的大小至少是m,根据题目来看最大是200. 我直接偷了懒,直接创建一个新的数组来存储(反正看的是后面一个解法)
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int a=0,b=0;
int s = 0;
int len = m+n;
int min = m < n ? m : n;
int[] nums3 = new int[m+n];
// 从两个列表中的未移动的部分头部哪个大
while(a <m && b <n) {
if(nums1[a]<nums2[b]){
nums3[s]=nums1[a++];
} else {
nums3[s]=nums2[b++];
}
s++;
}
// 将剩余nums1中的数据移动到nums3
while(a<m) nums3[s++]=nums1[a++];
// 将剩余nums2中的数据移动到nums3
while(b<n) nums3[s++]=nums2[b++];
// 覆盖nums1
for(int i=0;i<len;i++) {
nums1[i]=nums3[i];
}
}
}
上述解法存在的问题是需要额外的存储空间来存储,已知nums1已经是可以存储所有的结果的数组,能够在不创建新数组的情况完成合并? 上一种解法是从头部开始遍历,所以放置元素的时候与原数组出现了冲突,如果利用不会冲突的部分,也就nums1的尾部来存储元素将会解决该冲突。 与从头部遍历的方法的差异只需要替换遍历的方向即可。
class Solution {
private static final int MIN = -1;
public void merge(int[] nums1, int m, int[] nums2, int n) {
int a=m-1,b=n-1;
int s = m + n - 1;
// 两个列表都不为空的情况先移动大的
while(a > MIN && b > MIN) {
if(nums1[a]>nums2[b]){
nums1[s]=nums1[a--];
} else {
nums1[s]=nums2[b--];
}
s--;
}
// 将剩余nums1中的数据移动到nums1
while(a>MIN) nums1[s--]=nums1[a--];
// 将剩余nums2中的数据移动到nums1
while(b&gt;MIN) nums1[s--]=nums2[b--];
}
}