zoukankan      html  css  js  c++  java
  • leetcode

    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个数),直到递归的基本条件,这里面的一些思路算法我也还无法讲得很清楚,如果没太明白可以多看看其他文章

  • 相关阅读:
    自然语言交流系统 phxnet团队 创新实训 项目博客 (十一)
    install ubuntu on Android mobile phone
    Mac OS, Mac OSX 与Darwin
    About darwin OS
    自然语言交流系统 phxnet团队 创新实训 项目博客 (十)
    Linux下编译安装qemu和libvirt
    libvirt(virsh命令总结)
    深入浅出 kvm qemu libvirt
    自然语言交流系统 phxnet团队 创新实训 项目博客 (九)
    自然语言交流系统 phxnet团队 创新实训 项目博客 (八)
  • 原文地址:https://www.cnblogs.com/laihaiteng/p/3990773.html
Copyright © 2011-2022 走看看