4. 寻找两个正序数组的中位数
知识点:二分、归并排序
时间:2021年4月13日
题目链接
题目
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
示例 3:
输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000
示例 4:
输入:nums1 = [], nums2 = [1]
输出:1.00000
示例 5:
输入:nums1 = [2], nums2 = []
输出:2.00000
提示:
- nums1.length == m
- nums2.length == n
- 0 <= m <= 1000
- 0 <= n <= 1000
- 1 <= m + n <= 2000
- -106 <= nums1[i], nums2[i] <= 106
解题思路
- 要找到第 k (k>1) 小的元素,那么就取 pivot1 = nums1[k/2-1] 和 pivot2 = nums2[k/2-1] 进行比较 这里的 “/” 表示整除
- nums1 中小于等于 pivot1 的元素有 nums1[0 … k/2-2] 共计 k/2-1 个
- nums2 中小于等于 pivot2 的元素有 nums2[0 … k/2-2] 共计 k/2-1 个
- 取 pivot = min(pivot1, pivot2),两个数组中小于等于 pivot 的元素共计不会超过 (k/2-1) + (k/2-1) <= k-2 个
- 这样 pivot 本身最大也只能是第 k-1 小的元素
- 如果 pivot = pivot1,那么 nums1[0 … k/2-1] 都不可能是第 k 小的元素。把这些元素全部 “删除”,剩下的作为新的 nums1 数组
- 如果 pivot = pivot2,那么 nums2[0 … k/2-1] 都不可能是第 k 小的元素。把这些元素全部 “删除”,剩下的作为新的 nums2 数组
- 由于我们 “删除” 了一些元素(这些元素都比第 k 小的元素要小),因此需要修改 k 的值,减去删除的数的个数
- 注意边界的情况
代码
#include "cheader.h"
class Solution {
public:
int getKth(vector<int>& nums1,vector<int> &nums2, int k){
int index1 = 0,index2 =0;
int m = nums1.size(), n = nums2.size();
while(1){
if(index1 == m) //当一个数组中到头了 就返回另一个的
return nums2[index2+k-1];
else if(index2 == n)
return nums1[index1+k-1];
else if(k == 1) //只需要一个数时 比较即可
return min(nums1[index1],nums2[index2]);
int tmp = k/2-1; // 注意tmp >= m 或者 tmp >= n的情况
int newindex1 = min(index1 + tmp ,m-1);
int newindex2 = min(index2 + tmp ,n-1);
if(nums1[newindex1] <= nums2[newindex2]){
k -= newindex1-index1+1; //排除一定不是的解
index1 = newindex1+1; //更新下标
}else{
k -= newindex2-index2+1;
index2 = newindex2+1;
}
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int a = nums1.size() + nums2.size();
if(a % 2 == 1)
return getKth(nums1,nums2,(a+1)/2);
else
return (getKth(nums1,nums2,a/2) + getKth(nums1,nums2,a/2+1))/2.0;
}
double findMedianSortedArrays2(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size();
int n = nums2.size();
int x = 0,flag = 0;
if((m+n)%2 == 1){
flag = 0;
x = (m+n+1)/2;
}else{
flag = 1;
x = (m+n)/2+1;
}
vector<int> ans;
int tmp = 0,index1 = 0,index2 = 0;
while(tmp < x && index1 < m && index2 < n){
if(nums1[index1] >= nums2[index2]){
ans.push_back(nums2[index2]);
index2++;
tmp ++;
}
else{
ans.push_back(nums1[index1]);
index1++;
tmp++;
}
}
while(index1 == m && index2 < n && tmp < x){
ans.push_back(nums2[index2]);
index2++;
tmp ++;
}
while(index2 == n && index1 < m && tmp < x){
ans.push_back(nums1[index1]);
index1++;
tmp ++;
}
if(flag)
return 1.0*(ans[x-1]+ans[x-2])/2;
else
return 1.0*ans[x-1];
}
};
int main()
{
vector<int> nums1{2};
vector<int> nums2{};
Solution s;
cout << s.findMedianSortedArrays(nums1, nums2)<<endl;
return 0;
}
今天也是爱zz的一天哦!