leetcode 4 Median of Two Sorted Arrays

题目描述
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
中位数
对于 A[1, 2, ..., n]
如果 n 为奇数, (n+1)/2 是中位数, 如 9, (9+1)=5
如果 n 为偶数, (n+1)/2 是下中位数, 如 10, (10+1)/2=5
两个有序数组的第 k 小的数
总体思路: 找到并排除掉 k-1 个比第 kth 小的数
给予两个有序数组 A, B
\(A[1, 2, \cdots, n]\)
\(B[1, 2, \cdots, m]\)
为了找到第 k 个大小的数, 我们可以利用两个数组的有序特性, 排除掉 \(\left\lfloor \frac{k}{2} \right\rfloor\) 个非解空间中的数(即排除掉 \(\left\lfloor \frac{k}{2} \right\rfloor\) 个小于第 kth 小的数), 方法如下:
\(A[1,\cdots, \frac{k}{2}] \quad | \quad A[\frac{k}{2} + 1, \cdots, n]\)
\(B[1,\cdots, \frac{k}{2}] \quad | \quad B[\frac{k}{2} + 1, \cdots, m]\)
如果 \(A[\frac{k}{2}]\space \gt \space B[\frac{k}{2}]\), 那么 \(B[\frac{k}{2}]\) 最大只可能比 \(A[1,\cdots, \frac{k}{2}-1]+B[1,\cdots, \frac{k}{2}-1] 大,\)
即: \(B[\frac{k}{2}]\) 最大为第 \(\frac{k}{2}-1+\frac{k}{2}-1 + 1 = k-1\) 大的数
故: \(B[1,\cdots, \frac{k}{2}]\) 一定比第 k 小的数小, 可以排除
接下来只需要在 \(A[1, 2, \cdots, n] 和 B[\frac{k}{2} + 1, \cdots, m]\) 寻找 \(k - \left\lfloor \frac{k}{2} \right\rfloor\) 小的数就好了
依照上面的思路:
- 如果两个数组合并的数组大小为奇数, 我们就是寻找第 \(\frac{n+m+1}{2}\) 小的数;
- 如果两个数组合并的数组大小为偶数, 我们就是寻找第 \(\frac{n+m+1}{2}\) 小和第 \(\frac{n+m+1}{2}+1\)小的数的平均数;
Solution
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int len = nums1.size() + nums2.size();
int mid = (len+1)/2;
double median = kth(nums1, nums2, 0, 0, mid);
// 找第 k 个大小的值的起始值就是从 1 开始
// 所以中位数也是按照从 1 开始的计算
if (len%2 == 0) {
median = (median + kth(nums1, nums2, 0, 0, mid+1))/2.0;
}
return median;
}
int kth(vector<int>& nums1, vector<int>& nums2, int s1, int s2, int k) {
int len1 = nums1.size();
int len2 = nums2.size();
if (s1 == len1) return nums2[s2+k-1];
if (s2 == len2) return nums1[s1+k-1];
if (k == 1) return min(nums1[s1], nums2[s2]);
int step1 = min(k/2, len1-s1);
int step2 = min(k/2, len2-s2);
if (nums1[s1+step1-1] > nums2[s2+step2-1]) {
return kth(nums1, nums2, s1, s2+step2, k-step2);
}
return kth(nums1, nums2, s1+step1, s2, k-step1);
}
};