//对于长度为n的数组,当n为奇数时,其中位数只有一个,下标为(n-1)/2; n为偶数时,其中位数有上中位数和下中位数,下标分别为n/2-1 , n/2.
//已知有序数组A,B,长度分别为m,n。找出A,B(合并为一个大的有序数组后)中的中位数。要求时间复杂度为o(log(m+n)).
//此题中,若m+n为奇数,则返回下标为(n-1)/2的数;若为偶数,返回上中位数和下中位数的平均数。
/*
#include <iostream>
#include <math.h>
using namespace std;
double select_kth_num(int A[],int B[],int m,int n)
{
int k;
if((m+n)%2==1) //为奇数,则中位数只有一个
k = (m+n+1)/2; //第k个数即为中位数
else
k = (m+n)/2; //第k个数为上中位数,求出上中位数后下一个比它大的数即为下中位数,然后求平均
if (m==0)
{
if (n==1)
{
return B[0];
}
else
{
if(n%2==1)
return B[k-1]; //第k个数下标为k-1;
else
return (B[k-1]+B[k]+0.0)/2;
}
}
if (n==0)
{
if (m==1)
{
return A[0];
}
else
{
if (m%2==1)
{
return A[k-1];
}
else
return (A[k-1]+A[k]+0.0)/2;
}
}
if (m==1 && n==1)
{
return (A[0]+B[0]+0.0)/2;
}
int begin = 0;
int end = m-1;
int mid = (begin+end)/2; //先在数组A里面查找;mid为下标,若m为奇数,则mid指向正中间那个数;若为偶数,mid指向的是上中位数
// 则A中有mid个数小于A[mid]; 若A[mid]在B中刚好大于k-mid-1个数,则A[mid]为第k个数
while (mid >= k) // 此时A[mid]为A中至少是第k+1个数;不符合需缩小范围
{
end = mid-1;
mid = (begin+end)/2;
}
while (begin <= end)
{
mid = (begin+end)/2;
while (mid >= k) // 此时B[mid]为B中至少是第k+1个数;不符合需缩小范围,mid的最大值为k-1;
{
end = mid-1;
mid = (begin+end)/2;
}
if (k-mid-1 == 0)
{
if (A[mid]<=B[k-mid-1])
{
if((m+n)%2==1)
{
return A[mid]; //对于总数为奇数的情形
}
else
{
if (mid == m-1)
{
return (A[mid]+B[0]+0.0)/2.0;
}
else
{
return (A[mid]+std::min(B[0],A[mid+1])+0.0)/2.0;
}
}
}
else
{
if (A[mid]>B[k-mid-1]) //说明A,B中比A[mid]小的数的总个数大于k-1个,A[mid]取大了,应该在现在的位置的左边取
{
end = mid - 1;
}
else //说明A,B中比A[mid]小的数的总个数小于k-1个,A[mid]取小了,应该在现在的位置的右边取
{
begin = mid + 1;
}
}
}
else if (k-mid-1 > 0 && k-mid-1 < n)
{
if (A[mid]>=B[k-mid-2]&&A[mid]<=B[k-mid-1])
{
if((m+n)%2==1)
{
return A[mid]; //对于总数为奇数的情形
}
else
{ //当总个数为偶数,由于中位数自身的特点,mid==m-1时,k-mid-1不能同时到达n-1(除去m=n=1的情况);
if (mid == m-1) //为A中最后一个元素
{
double median = (A[mid] + B[k-mid-1]+0.0)/2;
return median;
}
else
{
int ss = A[mid+1]<=B[k-mid-1]?A[mid+1]:B[k-mid-1];
double median = (A[mid]+ss+0.0)/2;
return median;
}
}
//return (A[mid]+B[k-mid-1]+0.0)/2.0;
}
else
{
if (A[mid]>B[k-mid-1]) //说明A,B中比A[mid]小的数的总个数大于k-1个,A[mid]取大了,应该在现在的位置的左边取
{
end = mid - 1;
}
else //说明A,B中比A[mid]小的数的总个数小于k-1个,A[mid]取小了,应该在现在的位置的右边取
{
begin = mid + 1;
}
}
}
else if ( k-mid-1 == n) //B的长度刚好等于k-mid-1
{
if (A[mid]>=B[n-1]) // 此时只需A[mid] >= B[n-1]即可,此时A[mid]即为第k个数
{
if((m+n)%2==1)
{
return A[mid]; //对于总数为奇数的情形
}
else
return (A[mid]+A[mid+1]+0.0)/2.0;
}
else
{
begin = mid+1;
}
}
else//k-mid-1 > n ,此时超过了B中的长度,说明mid取小了
{
begin = mid+1;
}
}
//A中没有找到,则在B中找
begin = 0;
end = n-1;
mid = (begin+end)/2;
while (mid >= k) // 此时B[mid]为B中至少是第k+1个数;不符合需缩小范围,mid的最大值为k-1;
{
end = mid-1;
mid = (begin+end)/2;
}
while (begin <= end)
{
mid = (begin+end)/2;
while (mid >= k) // 此时B[mid]为B中至少是第k+1个数;不符合需缩小范围,mid的最大值为k-1;
{
end = mid-1;
mid = (begin+end)/2;
}
if (k-mid-1 == 0)
{
if (B[mid]<=A[k-mid-1])
{
if((m+n)%2==1)
{
return B[mid]; //对于总数为奇数的情形
}
else
{
if (mid == n-1)
{
return (B[mid]+A[0]+0.0)/2.0;
}
else
{
return (B[mid]+std::min(A[0],B[mid+1])+0.0)/2.0;
}
}
}
else
{
if (B[mid]>A[k-mid-1])
{
end = mid - 1;
}
else
{
begin = mid + 1;
}
}
}
else if (k-mid-1 > 0 && k-mid-1 < m)
{
if (B[mid]>=A[k-mid-2]&&B[mid]<=A[k-mid-1])
{
if((m+n)%2==1)
{
return B[mid]; //对于总数为奇数的情形
}
else
{
if (mid == n-1) //为B中最后一个元素
{
double median = (B[mid]+A[k-mid-1]+0.0)/2.0;
return median;
}
else
{
int ss = B[mid+1]<=A[k-mid-1]?B[mid+1]:A[k-mid-1];
double median = (B[mid]+ss+0.0)/2;
return median;
}
}
}
else
{
if (B[mid]>A[k-mid-1])
{
end = mid - 1;
}
else
{
begin = mid + 1;
}
}
}
else if ( k-mid-1 == m) //A的长度m刚好等于k-mid-1
{
if (B[mid]>=A[m-1]) // 此时只需B[mid] >= A[m-1]即可
{
if((m+n)%2==1)
{
return B[mid]; //对于总数为奇数的情形
}
else
return (B[mid]+B[mid+1]+0.0)/2.0;
}
else
{
begin = mid+1;
}
}
else
{
begin = mid+1;
}
}
}
int main()
{
int A[10] = {5,6,8,10,11,12,13,14,15,16},B[6] = {1,2,3,4,6,7};
double res = select_kth_num(A,B,5,6);
cout<<res<<endl;
system("pAuse");
return 0;
}
有序数组A,B的中位数
最新推荐文章于 2022-12-02 15:13:15 发布