有序数组A,B的中位数

//对于长度为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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值