java有序数组找中位数_有序数组中找中位数

题目:两个有序数组A和B,大小都是n,寻找这两个数组合并后的中位数。时间复杂度为O(logn)。

中位数:如果数组的个数是奇数,那么中位数的值就是有序时处于中间的数;如果数组个数是偶数的,那么就是有序时中间两个数的平均值。

方法一:合并时计数

使用Merge Sort时的Merge操作,比较两个数组时候计数,当计数达到n时,就可以得到中位数,在归并的数组中,中位数为下标n-1和n的两个数的平均值。

时间复杂度O(n)。

#include

/*This function returns median of ar1[] and ar2[].

Assumptions in this function:

Both ar1[] and ar2[] are sorted arrays

Both have n elements*/

int getMedian(int ar1[], int ar2[], intn)

{int i = 0; /*Current index of i/p array ar1[]*/

int j = 0; /*Current index of i/p array ar2[]*/

intcount;int m1 = -1, m2 = -1;/*Since there are 2n elements, median will be average of elements at index n-1 and n

in the array obtained after merging ar1 and ar2*/

for (count = 0; count <= n; count++)

{/*Below is to handle case where all elements of ar1[] are smaller than smallest(or first) element of ar2[]*/

if (i ==n)

{

m1=m2;

m2= ar2[0];break;

}/*Below is to handle case where all elements of ar2[] are smaller than smallest(or first) element of ar1[]*/

else if (j ==n)

{

m1=m2;

m2= ar1[0];break;

}if (ar1[i]

{

m1= m2; /*Store the prev median*/m2=ar1[i];

i++;

}else{

m1= m2; /*Store the prev median*/m2=ar2[j];

j++;

}

}return (m1 + m2)/2;

}/*Driver program to test above function*/

intmain()

{int ar1[] = {1, 12, 15, 26, 38};int ar2[] = {2, 13, 17, 30, 45};int n1 = sizeof(ar1)/sizeof(ar1[0]);int n2 = sizeof(ar2)/sizeof(ar2[0]);if (n1 ==n2)

printf("Median is %d", getMedian(ar1, ar2, n1));elseprintf("Doesn't work for arrays of unequal size");return 0;

}

方法二:比较两个数组的中位数

ar1[]和ar2[]为输入的数组

算法过程:

1.得到数组ar1和ar2的中位数m1和m2

2.如果m1==m2,则完成,返回m1或者m2

3.如果m1>m2,则中位数在下面两个子数组中

a) From first element of ar1 to m1 (ar1[0...|_n/2_|])

b) From m2 to last element of ar2 (ar2[|_n/2_|...n-1])

4.如果m1

a) From m1 to last element of ar1 (ar1[|_n/2_|...n-1])

b) From first element of ar2 to m2 (ar2[0...|_n/2_|])

5.重复上面的过程,直到两个子数组的大小都变成2

6.如果两个子数组的大小都变成2,使用下面的式子得到中位数:Median = (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1]))/2

时间复杂度:O(logn)。

#include

/*Utility functions*/

int max(int x, inty)

{return x > y?x : y;

}int min(int x, inty)

{return x > y?y : x;

}/*Function to get median of a sorted array*/

int median(int arr[], intn)

{if (n%2 == 0)return (arr[n/2] + arr[n/2-1])/2;else

return arr[n/2];

}/*This function returns median of ar1[] and ar2[].

Assumptions in this function:

Both ar1[] and ar2[] are sorted arrays

Both have n elements*/

int getMedian(int ar1[], int ar2[], intn)

{int m1; /*For median of ar1*/

int m2; /*For median of ar2*/

/*return -1 for invalid input*/

if (n <= 0)return -1;if (n == 1)return (ar1[0] + ar2[0])/2;if (n == 2)return (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1])) / 2;

m1= median(ar1, n); /*get the median of the first array*/m2= median(ar2, n); /*get the median of the second array*/

/*If medians are equal then return either m1 or m2*/

if (m1 ==m2)returnm1;/*if m1 < m2 then median must exist in ar1[m1....] and ar2[....m2]*/

if (m1

{if (n % 2 == 0)return getMedian(ar1 + n/2 - 1, ar2, n - n/2 +1);else

return getMedian(ar1 + n/2, ar2, n - n/2);

}/*if m1 > m2 then median must exist in ar1[....m1] and ar2[m2...]*/

else{if (n % 2 == 0)return getMedian(ar2 + n/2 - 1, ar1, n - n/2 + 1);else

return getMedian(ar2 + n/2, ar1, n - n/2);

}

}/*Driver program to test above function*/

intmain()

{int ar1[] = {1, 2, 3, 6};int ar2[] = {4, 6, 8, 10};int n1 = sizeof(ar1)/sizeof(ar1[0]);int n2 = sizeof(ar2)/sizeof(ar2[0]);if (n1 ==n2)

printf("Median is %d", getMedian(ar1, ar2, n1));elseprintf("Doesn't work for arrays of unequal size");return 0;

}

方法三:通过二分查找法来找中位数

基本思想是:假设ar1[i]是合并后的中位数,那么ar1[i]大于ar1[]中前i-1个数,且大于ar2[]中前j=n-i-1个数。通过ar1[i]和ar2[j]、ar2[j+1]两个数的比较,在ar1[i]的左边或者ar1[i]右边继续进行二分查找。对于两个数组 ar1[] 和ar2[], 先在 ar1[] 中做二分查找。如果在ar1[]中没找到中位数, 继续在ar2[]中查找。

算法流程:

1) 得到数组ar1[]最中间的数,假设下标为i.

2) 计算对应在数组ar2[]的下标j,j = n-i-1

3) 如果 ar1[i] >= ar2[j] and ar1[i] <= ar2[j+1],那么 ar1[i] 和 ar2[j] 就是两个中间元素,返回ar2[j] 和 ar1[i] 的平均值

4) 如果 ar1[i] 大于 ar2[j] 和 ar2[j+1] 那么在ar1[i]的左部分做二分查找(i.e., arr[left ... i-1])

5) 如果 ar1[i] 小于 ar2[j] 和 ar2[j+1] 那么在ar1[i]的右部分做二分查找(i.e., arr[i+1....right])

6) 如果到达数组ar1[]的边界(left or right),则在数组ar2[]中做二分查找

时间复杂度:O(logn)。

#include

/*A recursive function to get the median of ar1[] and ar2[] using binary search*/

int getMedianRec(int ar1[], int ar2[], int left, int right, intn)

{inti, j;/*We have reached at the end (left or right) of ar1[]*/

if(left >right)return getMedianRec(ar2, ar1, 0, n-1, n);

i= (left + right)/2;

j= n - i - 1; /*Index of ar2[]*/

/*Recursion terminates here.*/

if (ar1[i] > ar2[j] && (j == n-1 || ar1[i] <= ar2[j+1]))

{/*ar1[i] is decided as median 2, now select the median 1

(element just before ar1[i] in merged array) to get the average of both*/

if (ar2[j] > ar1[i-1] || i == 0)return (ar1[i] + ar2[j])/2;else

return (ar1[i] + ar1[i-1])/2;

}/*Search in left half of ar1[]*/

else if (ar1[i] > ar2[j] && j != n-1 && ar1[i] > ar2[j+1])return getMedianRec(ar1, ar2, left, i-1, n);/*Search in right half of ar1[]*/

else /*ar1[i] is smaller than both ar2[j] and ar2[j+1]*/

return getMedianRec(ar1, ar2, i+1, right, n);

}/*This function returns median of ar1[] and ar2[].

Assumptions in this function:

Both ar1[] and ar2[] are sorted arrays

Both have n elements*/

int getMedian(int ar1[], int ar2[], intn)

{//If all elements of array 1 are smaller then//median is average of last element of ar1 and first element of ar2

if (ar1[n-1] < ar2[0])return (ar1[n-1]+ar2[0])/2;//If all elements of array 1 are smaller then//median is average of first element of ar1 and//last element of ar2

if (ar2[n-1] < ar1[0])return (ar2[n-1]+ar1[0])/2;return getMedianRec(ar1, ar2, 0, n-1, n);

}/*Driver program to test above function*/

intmain()

{int ar1[] = {1, 12, 15, 26, 38};int ar2[] = {2, 13, 17, 30, 45};int n1 = sizeof(ar1)/sizeof(ar1[0]);int n2 = sizeof(ar2)/sizeof(ar2[0]);if (n1 ==n2)

printf("Median is %d", getMedian(ar1, ar2, n1));elseprintf("Doesn't work for arrays of unequal size");return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值