寻找正序中位数
题目描述:
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。
请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
难点
- 控制时间复杂度为O(log(m+n))
主体思路
- 复杂的带log应该考虑设计二分查找
- 同化奇偶情况为:查找 (m+n)/2 的数和查找 (m+n)/2+1 的数
- 广义考虑查找第K个数:
- 假设两个有序数组分别是 A 和 B。要找到第 k 个元素,我们可以比较 A[k/2-1]和 B[k/2−1],由于 A[k/2−1] 和 B[k/2−1] 的前面分别有 k/2-1 个元素,对于 A[k/2−1] 和 B[k/2−1] 中的较小值,最多只会有 k/2−2 个元素比它小,那么它就不能是第 k 小的数了。
- 因此可以归纳出三种情况:
- A[k/2-1] < B[k/2-1],则从截取之后的A子列开始
- A[k/2-1] > B[k/2-1],同上
- A[k/2-1] = B[k/2-1],可归到第一类
- 同时将k减去适当的值
- 应当考虑的是:
- k/2-1越界的时候,应该使用最后一个元素;减少k的时候也应该相应的减少。
代码
int getKInArray(int* nums1, int nums1Size, int* nums2, int nums2Size, int k){
int i=0, j=0;
while(1){
if(i+1>nums1Size) return nums2[j+k-1];。//貌似有bug
else if(j+1>nums2Size) return nums1[i+k-1];
else if(k==1) return ((nums1[i]>nums2[j])?nums2[j]:nums1[i]);
else{
int ni=i+k/2-1>=nums1Size?nums1Size-1:i+k/2-1;
int nj=j+k/2-1>=nums2Size?nums2Size-1:j+k/2-1;
if(nums1[ni]<=nums2[nj]){
k-=ni+1-i;
i=ni+1;
}
else{
k-=nj+1-j;
j=nj+1;
}
}
}
}
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size){
int k=(nums1Size+nums2Size+1)/2;
double n1=getKInArray(nums1, nums1Size, nums2, nums2Size, k);
k=(nums1Size+nums2Size+2)/2;
double n2=getKInArray(nums1, nums1Size, nums2, nums2Size, k);
return (n1+n2)/2.0;
}