88. Combine two ordered arrays¹
Give you two ordered array of integers nums1 and nums2 , you will nums2 merged into nums1 in the nums1 become an ordered array.
Description:
- Initialize the number of elements of nums1 and nums2 to m and n respectively .
- You can assume that nums1 has enough space (the size of the space is greater than or equal to m + n ) to store the elements in nums2 .
Example:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
Solution 1: Merge first and then sort
- Idea: Put nums2 into nums1 first, and then sort nums1
- the complexity
- Time: O(n*logn), based on sort
- Space:O(1)
public void merge(int[] nums1, int m, int[] nums2, int n) {
// 将nums2放入nums1
for (int i = 0; i < n; i++) {
nums1[i + m] = nums2[i];
}
// 排序
Arrays.sort(nums1);
}
Solution 2: Insert in reverse order
- Idea: Since inserting in order requires moving the elements behind, then I can go backwards and insert from the back forward
- the complexity
- Time:O(m + n)
- Space:O(1)
public void merge(int[] nums1, int m, int[] nums2, int n) {
// -1因为这里是索引
int i = m - 1, j = n - 1, k = m + n - 1;
while (i >= 0 && j >= 0) {
if (nums1[i] > nums2[j])
nums1[k--] = nums1[i--];
else
nums1[k--] = nums2[j--];
}
// 注:不用判断i>=0的情况,因为要放入nums1,且nums1已经是有序的
while (j >= 0) nums1[k--] = nums2[j--];
}
4. The median of two positively ordered arrays³
Given two sizes m and n are positive sequence (small to large) arrays nums1
and nums2
.
Please find the median of these two positive arrays, and the time complexity of the algorithm is required to be O(log(m + n)).
You can assume nums1
and nums2
will not be both empty.
Example 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
Solution one: merge
- Idea: Combine nums1 and nums2 into an array, use the merge method in merge sort, and then return.
- the complexity
- Time: O (m + n), but the running time on LeetCode is the same as the next
- Space:O(m + n)
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int total = nums1.length + nums2.length;
int[] tmp = new int[total]; // 创建一个新的大数组
int i = 0, j = 0, k = 0;
// 核心!
while (i < nums1.length && j < nums2.length)
tmp[k++] = nums1[i] <= nums2[j] ? nums1[i++] : nums2[j++];
// 处理未放入的情况
while (i < nums1.length) tmp[k++] = nums1[i++];
while (j < nums2.length) tmp[k++] = nums2[j++];
if ((total & 1) == 1) return tmp[total/2];
// 注:这里一定要转成double,因为默认int会舍去除的结果
else return (double)(tmp[total/2 - 1] + tmp[total/2])/2;
}
Solution 2: Binary search*
- the complexity
- Time:O(log(m+n))
- Space:O(1)
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int total = nums1.length + nums2.length;
if ((total & 1) == 1) {
// 这里+1是表示要寻找第k小的的元素
return findKthSmallestInSortedArrays(nums1, nums2, total/2 + 1);
} else {
double a = findKthSmallestInSortedArrays(nums1, nums2, total/2);
double b = findKthSmallestInSortedArrays(nums1, nums2, total/2 + 1);
return (a + b) / 2;
}
}
// 寻找第K小的元素
double findKthSmallestInSortedArrays(int[] nums1, int[] nums2, int k) {
// len来表示结束条件, base记录基准索引
int len1 = nums1.length, len2 = nums2.length, base1 = 0, base2 = 0;
while (true) {
// 结束条件:1.其中一个数组遍历完了 2.俩数组没走完,k走完了
// 注:-1 是因为k表示的是第n小,这里要转换为索引
if (len1 == 0) return nums2[base2 + k - 1];
if (len2 == 0) return nums1[base1 + k - 1];
if (k == 1) return Math.min(nums1[base1], nums2[base2]);
// 寻找第k小:在nums1找k/2小, nums2找k-i小
int i = Math.min(k/2, len1);
int j = Math.min(k-i, len2);
int a = nums1[base1 + i - 1];
int b = nums2[base2 + j - 1];
// 找到k,且元素相等的情况
if (i + j == k && a == b) return a;
// 更新两数组中小的 base,len,k
// 注:其中只有base是向后移动++,len和k都是--
if (a <= b) {
base1 += i;
len1 -= i;
k -= i;
}
if (a >= b) {
base2 += j;
len2 -= j;
k -= j;
}
}
}
}