15. [88]、合并两个有序数组
题目
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
你可以假设除了整数 0 之外,这个整数不会以零开头。
说明
- 初始化 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]
解法一
先合并再排序,时间复杂度为 O n l o g ( n ) Onlog(n) Onlog(n)
代码如下所示:
public void merge(int[] nums1, int m, int[] nums2, int n) {
for (int i = m, j = 0; i < m + n && j < n; i++, j++) {
nums1[i] = nums2[j];
}
Arrays.sort(nums1);
}
解法二
使用一个新的数组num1Copy
用来保存num1
数组中的值
使用插入排序,使用i,j,k分别表示num1Copy
、nums2
、nums1
数组的下标
num1Copy[i]
和nnum2[j]
进行比较,小的插入到num1
数组中,大的插入到后面,如果数组中有剩余的值,全部都插入到nums1
的后面。
时间复杂度为
O
(
n
)
O(n)
O(n),空间复杂度为
O
(
n
)
O(n)
O(n)。
public void merge(int[] nums1, int m, int[] nums2, int n) {
int[] nums1Copy = Arrays.copyOf(nums1, m);
int i = 0;
int j = 0;
int k = 0;
while (i < m && j < n) {
nums1[k++] = nums1Copy[i] < nums2[j] ? nums1Copy[i++] : nums2[j++];
}
if (i < m) {
System.arraycopy(nums1Copy, i, nums1, k, nums1.length - k);
}
if (j < n) {
System.arraycopy(nums2, j, nums1, k, nums1.length - k);
}
}
解法三
这种解法比较巧妙,因为num1
数组后面的位置都是空着的,所以从后往前比,将nums1[i]
和nums2[j]
中较大的值,放到最后面占据空着的值,以此类推,其实就是将数组中的值不断后移。最后如果num2
数组中有剩下的值,可以直接覆盖到nums1
数组中。
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i = m-1;
int j = n-1;
int k = nums1.length -1;
while (i >= 0 && j >= 0) {
nums1[k--] = nums1[i] > nums2[j] ? nums1[i--] : nums2[j--];
}
if (j >= 0) {
System.arraycopy(nums2, 0, nums1, 0, k);
}
}