//已知有序数组a,b,长度分别为m,n。找出a,b(合并为一个大的有序数组后)中第k个数。要求时间复杂度为o(log(m+n)).
//当k = (m+n-1)/2时,若m+n为奇数,则第k个数即为中位数;若m+n为偶数,第k个数即为下中位数。
/*
#include <iostream>
#include <math.h>
using namespace std;
int select_kth_num(int a[],int b[],int m,int n, int k)
{
int index = -1; //存放第k个数的下标
if (k>m+n || k<1)
{
return -1;
}
else
{
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) // 由于外层while每次结束时,begin或end有变化,再进入循环时的mid有可能大于k,因此仍需要缩小范围。
{
end = mid-1;
mid = (begin+end)/2;
}
if (k-mid-1 == 0)
{
if (a[mid]<=b[k-mid-1])
{
return a[mid];
}
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])
{
return a[mid];
}
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]即可
{
return a[mid];
}
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个数;不符合需缩小范围
{
end = mid-1;
mid = (begin+end)/2;
}
while (begin <= end)
{
mid = (begin+end)/2;
while (mid >= k) // 由于外层while每次结束时,begin或end有变化,再进入循环时的mid有可能大于k,因此仍需要缩小范围。
{
end = mid-1;
mid = (begin+end)/2;
}
if (k-mid-1 == 0)
{
if (b[mid]<=a[k-mid-1])
{
return b[mid];
}
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])
{
return b[mid];
}
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[n-1]即可
{
return b[mid];
}
else
{
begin = mid+1;
}
}
else //k-mid-1 > m ,此时超过了a中的长度,说明mid取小了
{
begin = mid+1;
}
}
}
}
int main()
{
int a[1] = {5},b[6] = {1,2,3,4,6,7};
int res;
for (int i = 0;i < 7;i++)
{
res = select_kth_num(a,b,1,6,i+1);
cout<<res<<endl;
}
//res = select_kth_num(a,b,8,2,4);
//cout<<res<<endl;
system("pause");
return 0;
}
有序数组a,b,找出a,b(合并为一个大的有序数组后)中第k个数
最新推荐文章于 2022-09-23 21:00:55 发布