leetcode - Median of Two Sorted Arrays
There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
找到两个有序数组的中位数(media),可以认为排序是从小到大的
先说下什么是中位数,如果元素数目是奇数,则是中间那个数,如果元素数目是偶数,则是中间两个数的平均值
这道题很容易的联想到归并的思路,用两个变量a和b从下标0开始分别去遍历A和B,较小的那个数的下标递增,直到遍历次数到达某个指定值(即中位数在整个序列中的位置排名),便找到了中位数,这个算法的时间复杂度是O(n+m)
代码:
1 class Solution { 2 public: 3 double findMedianSortedArrays(int A[], int m, int B[], int n) { 4 int total = m + n; 5 int middle = total / 2 + total % 2; 6 int count = 0; 7 int a = 0; 8 int b = 0; 9 int find = 0; 10 11 while (count != middle && a < m && b < n) 12 { 13 if (A[a] < B[b]) 14 { 15 find = A[a]; 16 ++a; 17 } 18 else 19 { 20 find = B[b]; 21 ++b; 22 } 23 ++count; 24 } 25 26 while (count != middle && a < m) 27 { 28 find = A[a]; 29 ++a; 30 ++count; 31 } 32 33 while (count != middle && b < n) 34 { 35 find = B[b]; 36 ++b; 37 ++count; 38 } 39 40 if (total & 0x1) //奇数 41 { 42 return find; 43 } 44 else 45 { 46 if (a < m && b < n) 47 { 48 find += A[a] < B[b] ? A[a] : B[b]; 49 return (double)find / 2; 50 } 51 if (a < m) 52 { 53 return (double)(find + A[a]) / 2; 54 } 55 if (b < n) 56 { 57 return (double)(find + B[b]) / 2; 58 } 59 } 60 61 return -1; 62 } 63 };
但是,题目要求时间复杂度O(log(m+n)),log级别的查找很容易想到二分,关于利用二分法来查找中位数,可以看看这篇文章:http://blog.csdn.net/yutianzuijin/article/details/11499917/,将题目转化为查找第k小的数(这道题里,第k小的数是中位数),我把思路注释在代码里了,可以结合代码看看:
1 class Solution { 2 public: 3 double findMedianSortedArrays(int A[], int m, int B[], int n) { 4 int total = m + n; 5 if (total & 0x1) //奇数 6 { 7 return findMedian(A, m, B, n, (m + n) / 2 + 1); 8 } 9 else 10 { 11 return (findMedian(A, m, B, n, (m + n) / 2 + 1) + findMedian(A, m, B, n, (m + n) / 2)) / 2; 12 } 13 } 14 //查找第k小的数 15 double findMedian(int A[], int m, int B[], int n, int k) 16 { 17 if (m > n) //始终保持A的长度不大于B 18 { 19 return findMedian(B, n, A, m, k); 20 } 21 if (m == 0) //若A的长度为0,则直接返回B的第k个数 22 { 23 return B[k - 1]; 24 } 25 if (k == 1) //k已无法再分,返回A[0]和B[0]中较小者 26 { 27 return A[0] < B[0] ? A[0] : B[0]; 28 } 29 //因为m不大于n,所以可能有m<(k/2),此时选取A的最后一个数即可 30 int a = k / 2 > m ? m : k / 2; 31 //选取B的前k-a个数,使得a+b=k,以便之后的比较可以删除a个或b个数(约k/2个),达到log级别的查询 32 int b = k - a; 33 34 if (A[a - 1] < B[b - 1]) //说明A[a - 1]到A[0]的数都在第k小的数之前,可以将它们都去除 35 { 36 return findMedian(A + a, m - a, B, n, k - a); 37 } 38 else if(A[a - 1] > B[b - 1]) //道理同上 39 { 40 return findMedian(A, m, B + b, n - b, k - b); 41 } 42 else //说明A[a - 1]或B[b - 1]刚好是第k小的数,返回即可 43 { 44 return A[a - 1]; 45 } 46 } 47 };
精髓在于findmedian这个方法,查找第k小的数,可设A的长度不大于B的长度(如果A的长度大于B的长度,交换一下即可),在A中取第k/2个数(因为A的长度是较小的,可能不够k/2,那么此时取最后一个数即可),在B中取第k - a个数,通过比较这两个数,可以每次去除a个数或b个数(约为k/2个数),直到递归的基本条件,这里面的一些思路算法我也还无法讲得很清楚,如果没太明白可以多看看其他文章
posted on 2014-09-24 15:11 laihaiteng 阅读(133) 评论(0) 编辑 收藏 举报