zoukankan      html  css  js  c++  java
  • LeetCode: Median of Two Sorted Arrays 解题报告

    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)).

    SOLTION 1:

    1. 我们借用findKthNumber的思想。先实现findKthNumber,如果是偶数个,则把中间2个加起来平均,奇数就用中间的。

    2. 为了达到LOG级的复杂度,我们可以这样:

    每次在A,B取前k/2个元素。有以下这些情况:

    1).  A的元素个数 < k/2. 则我们可以丢弃B前k/2. 反之亦然

    证明:

    我们使用反证法。

    假设第K大在B的前k/2中,例如位置在索引m(m <= k/2-1)那么A必然拥有前k中的k -(m+1)个元素,而

    m <= k/2-1,则 m+1 <= k/2  , k - (m+1) >= k/2与条件:A的元素不够k/2矛盾,所以假设不成立,得证。

    举个栗子:

    A: 6 7 8

    B: 1 2 3 4 5

    找第8大的数字,

    2). A[mid] < B[mid] (mid是k/2 -1索引处的元素)。

    这种情况下,我们可以丢弃A前k/2。

    证明:

    我们使用反证法。

    假设第K大在A的前k/2中记为maxK,例如位置在索引m(m <= k/2-1)那么B必然拥有前k中的k -(m+1)个元素,而

    m <= k/2-1,则 m+1 <= k/2  , k - (m+1) > k/2

    推出B[mid] <= maxK

    而A[mid] >= maxK 推出 A[mid]>=B[mid], 与题设矛盾。所以假设不能成立。

    举个栗子:

    A: 1 2

    B: 4 5 6 7 8

    找第四大的数字 我们就可以首先排除1,2.

     1 public double findMedianSortedArrays(int A[], int B[]) {
     2         if (A == null || B == null) {
     3             return 0;
     4         }
     5         
     6         int len = A.length + B.length;
     7         
     8         double ret = 0;
     9         // 偶数个元素
    10         if (len % 2 == 0) {
    11             ret = (findKth(A, B, 0, 0, len / 2) + findKth(A, B, 0, 0, len / 2 + 1)) / (double)2.0;
    12         } else {
    13             // 奇数个元素
    14             ret = findKth(A, B, 0, 0, len / 2 + 1);            
    15         }
    16         
    17         return ret;
    18     }
    19     
    20     // Find the Kth large number.
    21     public int findKth(int A[], int B[], int indexA, int indexB, int k) {
    22         int lenA = A.length;
    23         int lenB = B.length;
    24         
    25         if (indexA >= lenA) {
    26             return B[indexB + k - 1];
    27         } else if (indexB >= lenB) {
    28             return A[indexA + k - 1];
    29         }
    30         
    31         // Base Case, pay attention. 在这里必须要退出。因为k = 1的时候,不可能再分了。
    32         if (k == 1) {
    33             return Math.min(A[indexA], B[indexB]);
    34         }
    35         
    36         // -1是因为索引本身是从0开始的。而前k大元素含有k个元素。
    37         int mid = k / 2 - 1;
    38         
    39         // 注意,越界条件是 >= lenA. 怎么老是犯这个错误。。
    40         int keyA = indexA + mid >= lenA ? Integer.MAX_VALUE: A[indexA + mid];
    41         int keyB = indexB + mid >= lenB ? Integer.MAX_VALUE: B[indexB + mid];
    42         
    43         // 因为丢弃了k / 2个元素
    44         int kNew = k - k / 2;
    45         
    46         if (keyA < keyB) {
    47             return findKth(A, B, indexA + k / 2, indexB, kNew);
    48         } else {
    49             return findKth(A, B, indexA, indexB + k / 2, kNew);
    50         }
    51     }
    View Code

     2015.1.25

    可以优化一下,在找到kth number时可以及时退出:

     1 public class Solution {
     2     public double findMedianSortedArrays(int A[], int B[]) {
     3         //2257
     4         if (A == null || B == null) {
     5             return 0;
     6         }
     7         
     8         int len = A.length + B.length;
     9         if (len % 2 == 0) {
    10             return (double)(dfs(A, B, 0, 0, len / 2) + dfs(A, B, 0, 0, len / 2 + 1)) / 2.0;
    11         } else {
    12             return dfs(A, B, 0, 0, len / 2 + 1);
    13         }
    14     }
    15     
    16     public double dfs1(int A[], int B[], int aStart, int bStart, int k) {
    17         if (aStart >= A.length) {
    18             return B[bStart + k - 1];
    19         } else if (bStart >= B.length) {
    20             return A[aStart + k - 1];
    21         }
    22         
    23         if (k == 1) {
    24             return Math.min(A[aStart], B[bStart]);
    25         }
    26         
    27         // k = 4;
    28         // mid = 1;
    29         int mid = k / 2 - 1;
    30         
    31         if (aStart + mid >= A.length) {
    32             // drop the left side of B.
    33             return dfs(A, B, aStart, bStart + k / 2, k - k / 2);
    34         } else if (bStart + mid >= B.length) {
    35             // drop the left side of A.
    36             return dfs(A, B, aStart + k / 2, bStart, k - k / 2);
    37         } else if (A[aStart + mid] > B[bStart + mid]) {
    38             // drop the left side of B.
    39             return dfs(A, B, aStart, bStart + k / 2, k - k / 2);
    40         // 当2者相等,有2种情况:
    41         // 1. 当k为偶数,则kth存在于任何一个结尾处,其实也是可以丢弃一半的。
    42         // 2. 当k为奇数,则kth不存在于A,B的left side。也是可以丢弃任意一半。
    43         //} else if (A[aStart + mid] < B[bStart + mid]) {
    44         } else {
    45             return dfs(A, B, aStart + k / 2, bStart, k - k / 2);
    46         }
    47         
    48         //return A[aStart + mid];        
    49     }
    50     
    51     public double dfs(int A[], int B[], int aStart, int bStart, int k) {
    52         if (aStart >= A.length) {
    53             return B[bStart + k - 1];
    54         } else if (bStart >= B.length) {
    55             return A[aStart + k - 1];
    56         }
    57         
    58         if (k == 1) {
    59             return Math.min(A[aStart], B[bStart]);
    60         }
    61         
    62         // k = 4;
    63         // mid = 1;
    64         int mid = k / 2 - 1;
    65         
    66         if (aStart + mid >= A.length) {
    67             // drop the left side of B.
    68             return dfs(A, B, aStart, bStart + k / 2, k - k / 2);
    69         } else if (bStart + mid >= B.length) {
    70             // drop the left side of A.
    71             return dfs(A, B, aStart + k / 2, bStart, k - k / 2);
    72         } else if (A[aStart + mid] > B[bStart + mid]) {
    73             // drop the left side of B.
    74             return dfs(A, B, aStart, bStart + k / 2, k - k / 2);
    75         } else if (A[aStart + mid] < B[bStart + mid]) {
    76             return dfs(A, B, aStart + k / 2, bStart, k - k / 2);
    77         } else {
    78             // drop the left side of A.
    79             //return dfs(A, B, aStart + k / 2, bStart, k - k / 2);
    80             if (k % 2 == 0){
    81                 return A[aStart + mid];
    82             }
    83             
    84             // can drop both sides.
    85             return dfs(A, B, aStart + k / 2, bStart + k / 2, 1);
    86         }
    87         
    88         //return A[aStart + mid];        
    89     }
    90 }
    View Code

    GITHUB:

    https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/array/FindMedianSortedArrays.java

  • 相关阅读:
    【Hadoop】MapReduce练习:多job关联实现倒排索引
    【Hadoop】MapReduce练习:分科目等级并按分区统计学生以及人数
    【Zookeeper】利用zookeeper搭建Hdoop HA高可用
    【Linux】部署NTP时间同步服务器
    VSCode前端文件以服务器模式打开
    移动端公共方法封装
    常用浏览器及内核
    XHTML和HTML的区别
    javascript算法
    计算属性和侦听器
  • 原文地址:https://www.cnblogs.com/yuzhangcmu/p/4138184.html
Copyright © 2011-2022 走看看