LeetCode4. 寻找两个正序数组的中位数 思维和分治
LeetCode4. 寻找两个正序数组的中位数
题意
给定两个大小分别为
m和n的正序(从小到大)数组nums1和nums2。请你找出并返回这两个正序数组的 中位数 。
算法
问题转变为寻找两个正序数组中第k小的数是什么。
假设m,n >= k/2,我们分别在nums1和nums2数组分别选取k/2个数,
nums1[k/2 - 1] > nums2[k/2 - 1],可以排除nums2前k/2个数肯定不是中位数,接下来需要寻找第k - k/2数即可。nums1[k/2 - 1] <= nums2[k/2 - 1],可以排除nums1前k/2个数肯定不是中位数,接下来需要寻找第k - k/2数即可。
假设m < k/2,则我们从nums1中取m个元素,从nums2中取 k/2 个元素(由于 k=(n+m)/,因此 m,n 不可能同时小于 k/2.):
nums1[m - 1] > nums2[k/2 - 1],可以排除nums2前k/2个数肯定不是中位数,接下来需要寻找第k - k/2数即可。nums1[m - 1] <= nums2[k/2 - 1],可以排除nums1中的所有数肯定不是中位数,答案为nums2[k - m -1]数即可。
终止条件& 特殊条件:
- 因为两个数组不一定等长,程序交换一下为确保
nums1.size() <= nums2.size()即可,最后如果nums1全部用完,放回nums2[j+k]即可。 nums1有可能不够k/2个数,需要特殊判断if(k == 1),返回min(nums1[i], nums2[j])
时间复杂度分析: \(k=(m+n)/2\) ,且每次递归 \(k\) 的规模都减少一半,因此时间复杂度是 \(O(\log(m+n))\),
class Solution {
public:
int dfs(vector<int>& nums1, int i, vector<int>& nums2, int j, int k){
if(nums1.size() - i > nums2.size() - j) return dfs(nums2, j, nums1, i, k);
if(nums1.size() == i) return nums2[j + k - 1];
if(k == 1){
if(nums1.size() == i) return nums2[j + k - 1];
else return min(nums1[i], nums2[j]);
}
int a = min((int)nums1.size(), i + k / 2) - 1, b = j + k / 2 - 1;
if(nums1[a] > nums2[b])
return dfs(nums1, i, nums2, b + 1, k - (b - j + 1));
else
return dfs(nums1, a + 1, nums2, j, k - (a - i + 1));
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size() + nums2.size();
if(n & 1){
return 1.0 * dfs(nums1, 0, nums2, 0, n / 2 + 1);
}else{
return (dfs(nums1, 0, nums2, 0, n / 2) + dfs(nums1, 0, nums2, 0, n / 2 + 1)) / 2.0;
}
}
};

浙公网安备 33010602011771号