您的位置:首页 > 其它

给定两个已经排序好的数组,找到两者所有元素中第 k 大的元素

2017-03-28 15:33 399 查看
给定两个已经排序好的数组,找到两者所有元素中第 k 大的元素。假设为A,B都按升序排列。

 方法一: 直接 merge 两个数组(即将两个已排好序的数组合并为一个排好序的新数组(m+n个元素),然后求第 k 大的元素,时间复杂度为O(m + n);可以用一个计数器,记录当前已经找到第 m 大的元素了。同时我们使用两个指针
pA 和 pB,分别指向 A 和 B 数组的第一个元素,使用类似于 merge sort 的原理,如果数组 A 当前元素小,那么 pA++,同时 m++;如果数组
B 当前元素 小,那么 pB++,同时 m++。最终当 m 等于 k 的时候,就得到了我们的答案,O(k)时间,O(1) 空间。但是,当 k 很接近 m + n 的时候,这个方法时间复杂还是 O(m + n) 。

C++代码:
int findKthMaxNumOfArrays(int A[],int m,int B[],int n,int k)
{
    int *pA=A;
    int *pB=B;
    int i=0;
    int j=0;
    int cur=0;
    while(i<m&&j<n)            
    {
        if(A[i]<B[j])
        {
            cur++;
            if(cur==k) return A[i];
            i++;
        }
        else 
        {
            cur++;
            if(cur==k) return B[j];
            j++;
        }
    }
    while(i<m)                    
    {
        cur++;
        if(cur==k) return A[i];
        i++;
    }
    while(j<n)                   
    {
        cur++;
        if(cur==k) return B[j];
        j++;
    }

方法二: 由于 A 和 B 都是有序的,利用这里面的信息,类似于二分查找。时间复杂度可以缩短到


              假设 A 和 B 的元素个数都大于 k/2,我们将 A 的第 k/2 个元素(即 A[k/2-1])和 B 的第 k/2个元素(即 B[k/2-1])进行比较,

             有以下三种情况(为了简化这里先假设 k 为偶数,所得到的结论对于 k 是奇数也是成立的):

                • A[k/2-1] == B[k/2-1]

                • A[k/2-1] > B[k/2-1]

                • A[k/2-1] < B[k/2-1]

              如果 A[k/2-1] < B[k/2-1],意味着 A[0] 到 A[k/2-1 ]的肯定在 A ∪ B 的 top k 元素的范围内,换句话说,A[k/2-1 ]不可能大于 A ∪                B 的第 k 大元素。因此,我们可以放心的删除 A 数组的这 k/2 个元素。同理,当 A[k/2-1]
> B[k/2-1] 时,可以删除 B 数组的 k/2              个元素。当 A[k/2-1] == B[k/2-1] 时,说明找到了第 k 大的元素,直接返回 A[k/2-1] 或 B[k/2-1]

           因此,我们可以写一个递归函数。那么函数终止条件如下:

              • 当 A 或 B 是空时,直接返回 B[k-1] 或 A[k-1];

              • 当 k=1 是,返回 min(A[0], B[0]);

              • 当 A[k/2-1] == B[k/2-1] 时,返回 A[k/2-1] 或 B[k/2-1]

int findKthMaxNumOfArrays(int A[],int m,int B[],int n,int k)
{
if(m>n)
return findKthMaxNumOfArrays(B,n,A,m,k);  //假设m永远<=n;
if(m==0)
return B[k-1];
if(k==1)
return ((A[0]>=B[0]?B[0]:A[0]));
int k2=k>>1;
int pA=((k2>=m)?m:k2);
int pB=k-pA;
if(A[pA-1]<B[pB-1])
return findKthMaxNumOfArrays(A+pA,m-pA,B,n,k-pA);
else if(A[pA-1]>B[pB-1])
return findKthMaxNumOfArrays(A,m,B+pB,n-pB,k-pB);
else
return A[pA-1];
}
 

方法三、判断a[mid_a] 与 b[mid_b]的关系(同二类似)

 如果A[mida] < B[mid_b]

 1)k小于等于mida + midb + 1,那么B数组从mid_b开始就没有用了,缩小B的搜索范围

 2)k大于mida + midb + 1, 那么A数组从low到mid_a开始就没用了,缩小A的搜索范围

 3)终止条件是 A搜索完 返回B中元素或者相反

找到两者所有元素的中位数

int findMedianSortedArrays(int A[], int m, int B[], int n)
    {
        int total = m + n;
        if (total & 0x1) 
            return findKth(A, m, B, n, total / 2 + 1);    //m+n为奇数
        else
            return (findKth(A, m, B, n, total / 2)
                    + findKth(A, m, B, n, total / 2 + 1)) / 2; //m+n为偶数
    } 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐