给定两个大小为 m 和 n 的有序数组 a 和 b。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 a 和 b 不会同时为空。
#include<stdio.h>
#include<math.h>
#define min(a,b) a<b?a:b
double dg(int* a, int x1, int* b, int x2, int k, int length_a, int length_b);
double find(int* nums1, int nums1Size, int* nums2, int nums2Size){
int k = 0, l;
l = nums1Size + nums2Size;
double m, n;
l % 2 == 1 ? (k = l / 2 + 1) : (k = l / 2);
if (nums1Size == 0){
if (l % 2 == 1){
m = nums2[k - 1];
}
else if (l % 2 == 0){
m = nums2[k - 1];
n = nums2[k];
m = (m + n) / 2;
}
return m;
}
else if (nums2Size == 0){
if (l % 2 == 1){
m = nums1[k - 1];
}
else if (l % 2 == 0){
m = nums1[k - 1];
n = nums1[k];
m = (m + n) / 2;
}
return m;
}
if (l % 2 == 1){
return dg(nums1, 0, nums2, 0, k - 1,nums1Size,nums2Size);
}
double x = dg(nums1, 0, nums2, 0, k,nums1Size, nums2Size);
printf("x %f\n", x);
double y = dg(nums1, 0, nums2, 0, k + 1, nums1Size, nums2Size);
printf(" y %f \n", y);
// printf("xy %f \n", (x + y) / 2);
return (x+y)/2;
}
double dg(int* a, int x1, int* b, int x2, int k,int length_a,int length_b){
int i = 0;
int g1 = 100, g2 = 100;//我这里定义100,是因为c语言里没有极大,
if (x1 >= length_a) { /*x1和x2用来排除较小数组的k/2的前半部分;以及作为递归结束的条件,当x的值大于数组长度时候说明已经遍历完那一数组,则第k个数在另一个数组。*/
return b[x2 + k - 1];
}
if (x2 >= length_b) return a[x1 + k - 1];
if (k == 1) {
return min(a[x1], b[x2]);
}
int g1 = 100, g2 = 100;/*我这里定义100,是因为c语言里没有极大;这是为了避免k/2大数组长度的情况下发生错误;但是有更巧妙的方法,我就不写了。
if (x1 + k / 2 - 1 < length_a){
g1 = a[x1 + k / 2 - 1];
}
if (x2 + k / 2 - 1 < length_b){
g2 = b[x2 + k / 2 - 1];
}
if (g1 < g2){
return (dg(a, x1 + k / 2, b, x2, k - k / 2,length_a,length_b));//当a数组的g1<b的g2时,x1向后移动排除a数组之前g1的值
}
return (dg(a, x1, b, x2 + k / 2, k - k / 2, length_a,length_b));
}
void main(){
int a[2] = { 1, 2 }, nums2[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
double aa = 0;
aa = find(a, 2, nums2, 10);
printf("%f", aa);
}
解题实现思路:
这一题可以当作是寻找第 k =(m + n)/ 2个数,常规方法是合并排序然后求中位数,但是有时间要求,不能使用合并排序。
解法一:根据中位数的特性,可以构造一个小堆,最右边的孩子就是中位数;
解法二:我使用的就是这个解法,由于这是两个有序数组,可以使用 a数组中的第 k/2个是和b数组的k/2个数比较大小。第k个数一定再较小那一数组的后半部分,或者较大数组的前半部分。然后进行递归,具体可以看代码注释;