题目描述
有两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。编写一个方法,将 B 合并入 A 并排序。
初始化 A 和 B 的元素数量分别为 m 和 n。
示例
输入:
A = [1,2,3,0,0,0]
B = [2,5,6]
输出:
[1,2,2,3,5,6]
解法一:双指针法
思路:
使用双指针法,从 A 数组和 B 数组的末尾开始比较两个数组的元素,将较大的元素放到 A 数组的末尾。
具体过程如下:
- 初始化双指针 i 和 j 分别指向 A 数组和 B 数组的末尾。
- 初始化指针 k 指向 A 数组的最后一个元素。
- 从后往前比较 A[i] 和 B[j],将较大的元素放到 A[k] 的位置上,同时将指针 i、j 和 k 向前移动一位。
- 如果 A 数组遍历结束了,将 B 数组中剩余的元素复制到 A 数组中。
时间复杂度为 O ( m + n ) O(m+n) O(m+n),其中 m 和 n 分别是 A 数组和 B 数组的长度。
代码:(双指针法,时间复杂度 O ( m + n ) O(m+n) O(m+n))
class Solution {
public void merge(int[] A, int m, int[] B, int n) {
int i = m - 1, j = n - 1, k = m + n - 1;
while (i >= 0 && j >= 0) {
if (A[i] > B[j]) {
A[k] = A[i];
i--;
} else {
A[k] = B[j];
j--;
}
k--;
}
while (j >= 0) {
A[k] = B[j];
j--;
k--;
}
}
}
解法二:归并排序
思路:
将 A 数组的前 m 个元素和 B 数组合并成一个有序数组,然后将其复制到 A 数组中。
具体过程如下:
- 将 A 数组的前 m 个元素和 B 数组复制到一个新的数组中,记为 C 数组。
- 对 C 数组进行归并排序,排序完成后将 C 数组的元素复制回 A 数组。
时间复杂度为 O ( ( m + n ) log ( m + n ) ) O((m+n)\log(m+n)) O((m+n)log(m+n)),其中 m 和 n 分别是 A 数组和 B 数组的长度。
代码:(归并排序,时间复杂度 O ( ( m + n ) log ( m + n ) ) O((m+n)\log(m+n)) O((m+n)log(m+n)))
class Solution {
public void merge(int[] A, int m, int[] B, int n) {
int[] C = new int[m + n];
System.arraycopy(A, 0, C, 0, m);
System.arraycopy(B, 0, C, m, n);
mergeSort(C, 0, m + n - 1);
System.arraycopy(C, 0, A, 0, m + n);
}
private void mergeSort(int[] nums, int left, int right) {
if (left >= right) {
return;
}
int mid = (left + right) >>> 1;
mergeSort(nums, left, mid);
mergeSort(nums, mid + 1, right);
merge(nums, left, mid, right);
}
private void merge(int[] nums, int left, int mid, int right) {
int[] tmp = new int[right - left + 1];
int i = left, j = mid + 1, k = 0;
while (i <= mid && j <= right) {
if (nums[i] <= nums[j]) {
tmp[k++] = nums[i++];
} else {
tmp[k++] = nums[j++];
}
}
while (i <= mid) {
tmp[k++] = nums[i++];
}
while (j <= right) {
tmp[k++] = nums[j++];
}
System.arraycopy(tmp, 0, nums, left, right - left + 1);
}
}