zoukankan      html  css  js  c++  java
  • 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)).

    分析:

       其实这题更通用的形式是,给定两个已经排好序的数组,找到两者所有元素中第k大的元素。

       O(m+n)的解法比较直观,直接merge两个数组,然后取第k个元素即可。

       不过我们仅仅需要第k大的元素,是不需要“排序”这么复杂的操作的。可以用一个计数器,记录当前已经找到第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)的。

    实现代码:

    #include<stdio.h>
    static int g_InvlidInput = 0;
    int find_kth(int A[],int m, int B[], int n,int k)
    {
        if((m+n)<k)
        {
            g_InvlidInput = 1;
            return -1;
        }
        int kth = 0,kthindex = 0,Aindex = 0,Bindex = 0;
        int *pA = A;
        int *pB = B;
        while((kthindex < k) && (Aindex < m) && (Bindex < n))
        {
            if(pA[Aindex] <pB[Bindex])
            {
                kth = pA[Aindex];
                Aindex++;
            }else
            {
                kth = pB[Bindex];
                Bindex++;
            }
            kthindex++;
        }
        if(kthindex == k)
            return kth;
        else
        {
            if(Aindex == m) return pB[Bindex+k-kthindex];
            if(Bindex == n) return pA[Aindex+k-kthindex];
        }
    }
    
    //test
    int main()
    {
        int A[] ={1,4,5,7,9,22,44,78};
        int B[] ={2,4,7,11,12,23,45};
        int result = find_kth(A,8,B,7,8);
        if(g_InvlidInput)
            printf("Invaild Input!");
        else 
            printf("%d
    ",result);
        return 0;
    }

    除了这个方案,还有没有更好的方案呢?有。我们可以考虑从k入手。如果我们每次都删除一半呢》由于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]的元素肯定在AUB的top k元素的范围内,也就是说,A[K/2-1]不可能大于AUB的第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]

    实现代码:

    #include<stdio.h>
    int min(int a, int b)
    {
        if(a>b)
            return b;
        else
            return a;
    }
    int find_kth(int A[],int m, int B[], int n,int k)
    {
        //保证m比n小
        if(m >n) return find_kth(B,n,A,m,k);
        if(m == 0) return B[k-1];
        if(k == 1) return min(A[0],B[0]);
    
        //将k拆分成两个部分
        int pa = min(k/2,m),pb = k -pa;
        if(A[pa-1] < B[pb-1])
            return find_kth(A+pa,m-pa,B,n,k-pa);
        else if( A[pa-1] >B[pb-1])
            return find_kth(A,m,B+pb,n-pb,k-pb);
        else
            return A[pa-1];
    }
    
    //test
    int main()
    {
        int A[] ={1,4,5,7,9,22,44,78};
        int B[] ={2,4,7,11,12,23,45};
        int result = find_kth(A,8,B,7,10);
        printf("%d
    ",result);
        return 0;
    }
  • 相关阅读:
    SpringCloud 第一篇:服务的注册和发现(Eureka)
    微服务架构
    SpringMvc的工作原理
    《即时消息技术剖析与实战》学习笔记7——IM系统的消息未读
    《MySQL实战45讲》学习笔记3——InnoDB为什么采用B+树结构实现索引
    《即时消息技术剖析与实战》学习笔记6——IM系统如何保证消息的安全性
    《即时消息技术剖析与实战》学习笔记5——IM系统如何保证消息的一致性
    《即时消息技术剖析与实战》学习笔记4——IM系统如何保证消息的可靠性
    《即时消息技术剖析与实战》学习笔记3——IM系统如何保证消息的实时性
    《即时消息技术剖析与实战》学习笔记2——支持用户点对点聊天的消息收发架构
  • 原文地址:https://www.cnblogs.com/neyer/p/4519399.html
Copyright © 2011-2022 走看看