有序数组A,B的中位数

来源:互联网 发布:牛耳软件教育 编辑:程序博客网 时间:2024/09/21 08:56
//对于长度为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个数即为中位数elsek = (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;elsereturn (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];}elsereturn (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];  //对于总数为奇数的情形}elsereturn (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];  //对于总数为奇数的情形}elsereturn (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
原创粉丝点击