There are two sorted arrays nums1 and nums2 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)).

Example 1:

  1. nums1 = [1, 3]
  2. nums2 = [2]
  3.  
  4. The median is 2.0

Example 2:

  1. nums1 = [1, 2]
  2. nums2 = [3, 4]
  3.  
  4. The median is (2 + 3)/2 = 2.5

分析:关键在于理解中位数的实际含义,即将一群数分割成数目相同的两部分,并且右边的数始终不小于(大于或等于)左边的数,也就是右边的最小值大于等于左边的最大值。明白了这个,在去解这题,对于整数数组 A[0~m] 和 整数数组 B[0~n],在0~m中寻找分割位 i,在 0~n 中寻找分割位 j

First let's cut A into two parts at a random position i:

  1. left_A | right_A
  2. A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1]

Since A has m elements, so there are m+1 kinds of cutting( i = 0 ~ m ). And we know: len(left_A) = i, len(right_A) = m - i . Note: when i = 0 , left_A is empty, and when i = m , right_A is empty.

With the same way, cut B into two parts at a random position j:

  1. left_B | right_B
  2. B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]

Put left_A and left_B into one set, and put right_A and right_B into another set. Let's name them left_part and right_part :

  1. left_part | right_part
  2. A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1]
  3. B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1]

(上面要注意的是可能构成左,右部分的只有A或B,即A和B被全部扔到了左边部分或右边部分)

If we can ensure:

  1. 1) len(left_part) == len(right_part)
  2. 2) max(left_part) <= min(right_part)

then we divide all elements in {A, B} into two parts with equal length, and one part is always greater than the other. Then median = (max(left_part) + min(right_part))/2.

To ensure these two conditions, we just need to ensure:

  1. (1) i + j == m - i + n - j (or: m - i + n - j + 1)
  2. if n >= m, we just need to set: i = 0 ~ m, j = (m + n + 1)/2 - i
  3. (2) B[j-1] <= A[i] and A[i-1] <= B[j]

上面之所以加1是考虑到了 m+n 是奇数的情形,如果m+n是偶数(m=3, n=3),比如是6,那么加1除2和不加1除2结果是一样的都是3,这是如果i=2,那么j=1,left_part是(A[0],A[1],B[0]),right_part是(A[2],B[1],B[2])。如果m+n是奇数(m=3,n=4),7+1除2结果是4,如果i=2,那么j=2,left_part是(A[0],A[1],B[0],B[1]),right_part是(A[2],B[2],B[3])。这时左右部分个数并不相等,因为对于总数为奇数的情形来说本来就不能将其分为个数相等的两个部分,不过从上面的分析可以得知,在总数是偶数时可以保证两部分个数相等,此时的中位数等于左边部分的最大值加上右边部分的最小值再除以2,当总数是奇数时可以保证中位数分到了左边部分,即此时的中位数等于左边部分的最大值。

So, all we need to do is:

  1. Searching i in [0, m], to find an object `i` that:
  2. B[j-1] <= A[i] and A[i-1] <= B[j], ( where j = (m + n + 1)/2 - i )

上面要确保m<n,否则索引会出现负数,如果开始输入的两个数组其长度m>n,代码上交换一下数组即可。

And we can do a binary search following steps described below:

  1. <1> Set imin = 0, imax = m, then start searching in [imin, imax]
  2. <2> Set i = (imin + imax)/2, j = (m + n + 1)/2 - i
  3. <3> Now we have len(left_part)==len(right_part). And there are only 3 situations
  4. that we may encounter:
  5. <a> B[j-1] <= A[i] and A[i-1] <= B[j]
  6. Means we have found the object `i`, so stop searching.
  7. <b> B[j-1] > A[i]
  8. Means A[i] is too small. We must `ajust` i to get `B[j-1] <= A[i]`.
  9. Can we `increase` i?
  10. Yes. Because when i is increased, j will be decreased.
  11. So B[j-1] is decreased and A[i] is increased, and `B[j-1] <= A[i]` may
  12. be satisfied.
  13. Can we `decrease` i?
  14. `No!` Because when i is decreased, j will be increased.
  15. So B[j-1] is increased and A[i] is decreased, and B[j-1] <= A[i] will
  16. be never satisfied.
  17. So we must `increase` i. That is, we must ajust the searching range to
  18. [i+1, imax]. So, set imin = i+1, and goto <2>.
  19. <c> A[i-1] > B[j]
  20. Means A[i-1] is too big. And we must `decrease` i to get `A[i-1]<=B[j]`.
  21. That is, we must ajust the searching range to [imin, i-1].
  22. So, set imax = i-1, and goto <2>.

When the object i is found, the median is:

  1. max(A[i-1], B[j-1]) (when m + n is odd)
  2. or (max(A[i-1], B[j-1]) + min(A[i], B[j]))/2 (when m + n is even)

Now let's consider the edges values i=0,i=m,j=0,j=n where A[i-1],B[j-1],A[i],B[j] may not exist. Actually this situation is easier than you think.

What we need to do is ensuring that max(left_part) <= min(right_part). So, if i and j are not edges values(means A[i-1],B[j-1],A[i],B[j] all exist), then we must check both B[j-1] <= A[i] and A[i-1] <= B[j]. But if some of A[i-1],B[j-1],A[i],B[j] don't exist, then we don't need to check one(or both) of these two conditions. For example, if i=0, then A[i-1] doesn't exist, then we don't need to check A[i-1] <= B[j]. So, what we need to do is:

  1. Searching i in [0, m], to find an object `i` that:
  2. (j == 0 or i == m or B[j-1] <= A[i]) and
  3. (i == 0 or j == n or A[i-1] <= B[j])
  4. where j = (m + n + 1)/2 - i

And in a searching loop, we will encounter only three situations:

  1. <a> (j == 0 or i == m or B[j-1] <= A[i]) and
  2. (i == 0 or j = n or A[i-1] <= B[j])
  3. Means i is perfect, we can stop searching.
  4. <b> j > 0 and i < m and B[j - 1] > A[i]
  5. Means i is too small, we must increase it.
  6. <c> i > 0 and j < n and A[i - 1] > B[j]
  7. Means i is too big, we must decrease it.

As: i < m ==> j > 0 and i > 0 ==> j < n . Because:

  1. m <= n, i < m ==> j = (m+n+1)/2 - i > (m+n+1)/2 - m >= (2*m+1)/2 - m >= 0
  2. m <= n, i > 0 ==> j = (m+n+1)/2 - i < (m+n+1)/2 <= (2*n+1)/2 <= n

So in situation <b> and <c>, we don't need to check whether j > 0 and whether j < n.

上面是在考虑边界的情形,在搜索 i 的过程中,因为 j = (m + n + 1)/2 - i,所以我们只需要关注中位数的第二个条件即可,即右边部分的最小值不小于左边部分的最大值,对于分割位i和j,因为数组A和B自身已经是排过序的了,所以首先想到的是比较A[i-1]和B[j],以及B[j-1]和A[i].但是如果i=0,i=m以及j=0,j=m 时该如何判断,以i=0为例,这中情况表明A数组所有数被分到了右边的部分,这种情况大概发生在B数组的个数远大于A数组的情形,此时的中位数在完全的B数组中寻找,j = (m + n + 1)/2 - i,那么j取到的位置就是中间位置,如果此时B[j-1]<=A[i],保证了左边的最大小于或等于右边所有的数,那j的位置就是中位数的位置(或j-1和j)。分析了这么多,其实结论就一个,也就是说当i=0时,只需要满足情形a中与判断的第一条件即可。

代码:

  1. class Solution {
  2. public double findMedianSortedArrays(int[] nums1, int[] nums2) {
  3. int m=nums1.length;
  4. int n=nums2.length;
  5. int[] A=nums1;
  6. int[] B=nums2;
  7. if(m>n){
  8. int temp1=m;
  9. m=n;
  10. n=temp1;
  11. int[] temp2=A;
  12. A=B;
  13. B=temp2;
  14. }
  15.  
  16. int max_left=0;
  17. int min_right=0;
  18. // i+j=m-i+n-j+1
  19. int imin=0,imax=m,half_len=(m+n+1)/2;//出于奇偶的考虑
  20. while(imin<=imax){
  21. int i=(imin+imax)/2;
  22. int j=half_len-i;
  23. if(i<m && B[j-1]>A[i]) imin=i+1;
  24. else if(i>0 && A[i-1]>B[j]) imax=i-1;
  25. else{
           // i is perfect,先求max_left再求max_right
  26. if(i==0){        // A被全部放到了右边
  27. max_left=B[j-1];
  28. }else if(j==0){    // B被全部放到了右边
  29. max_left=A[i-1];
  30. }else{         // 一般情形
  31. max_left=Math.max(A[i-1],B[j-1]);
  32. }
  33.  
  34. if((m+n)%2==1) return max_left;
  35.  
  36. if(i==m){
  37. min_right=B[j];
  38. }else if(j==n){
  39. min_right=A[i];
  40. }else{
  41. min_right=Math.min(A[i],B[j]);
  42. }
  43. return (max_left+min_right)/2.0;
  44. }
  45. }
  46. return -1;
  47. }
  48. }

LeetCode解题报告—— Median of Two Sorted Arrays的更多相关文章

  1. 《LeetBook》leetcode题解(4): Median of Two Sorted Arrays[H]——两个有序数组中值问题

    我现在在做一个叫<leetbook>的免费开源书项目,力求提供最易懂的中文思路,目前把解题思路都同步更新到gitbook上了,需要的同学可以去看看 书的地址:https://hk029.g ...

  2. 【LeetCode】4. Median of Two Sorted Arrays (2 solutions)

    Median of Two Sorted Arrays There are two sorted arrays A and B of size m and n respectively. Find t ...

  3. leetcode.C.4. Median of Two Sorted Arrays

    4. Median of Two Sorted Arrays 这应该是最简单最慢的方法了,因为本身为有序,所以比较后排序再得到中位数. double findMedianSortedArrays(in ...

  4. 【一天一道LeetCode】#4 Median of Two Sorted Arrays

    一天一道LeetCode (一)题目 There are two sorted arrays nums1 and nums2 of size m and n respectively. Find th ...

  5. 【LeetCode OJ】Median of Two Sorted Arrays

    题目链接:https://leetcode.com/problems/median-of-two-sorted-arrays/ 题目:There are two sorted arrays nums1 ...

  6. 【LeetCode】4. Median of Two Sorted Arrays 寻找两个正序数组的中位数

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:数组,中位数,题解,leetcode, 力扣,python ...

  7. 【leetcode】4. Median of Two Sorted Arrays

    题目描述: There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of t ...

  8. leetcode第二题--Median of Two Sorted Arrays

    Problem:There are two sorted arrays A and B of size m and n respectively. Find the median of the two ...

  9. Leetcode Array 4 Median of Two Sorted Arrays

    做leetcode题目的第二天,我是按照分类来做的,做的第一类是Array类,碰见的第二道题目,也就是今天做的这个,题目难度为hard.题目不难理解,但是要求到了时间复杂度,就需要好好考虑使用一下算法 ...

随机推荐

  1. AOJ.562 寻找罗恩和赫敏

    寻找罗恩和赫敏 考察点 水题 Time Mem Len Lang 0 492KB 0.42K G++ 题意分析 计算1/C(n,2)的值 代码总览 /* Title:AOJ.562 Author:pe ...

  2. codevs5037 线段树练习4加强版(暴力分块)

    求大爷教线段树怎么写啊QAQ 只会写分块...一开始脑抽写成了O(NKlogN)还被CZL大爷嘲讽了一发T T f[i][j]表示在第i块中,模k为j的数有几个,然后每次修改的时候只需要打个标记,查询 ...

  3. GoLand安装配置

    目录 下载 安装 破解 运行 参考网址 GoLand配置 下载 1 下载路径:https://pan.baidu.com/s/1JJ-Oxx9NkEK-PrwcvLys7Q,提取码:o0e5 2 下载 ...

  4. c++11新特性之nullptr

    在c++11中,nullptr可完全代替NULL.  然而NULL和nullptr还是稍有不同,NULL可被转化为int类型,而nullptr不能.因此nullptr对NULL在进行模板推导或者函数重 ...

  5. 第八周 yukun 20155335

  6. VSCode Web Developement for Javascript. Must have plugins.

    Es6 Javascript front-end web developemnt must have plugins Prettier - Code Formatter Javascript (ES6 ...

  7. HDU 2577 How to Type (字符串处理)

    题目链接 Problem Description Pirates have finished developing the typing software. He called Cathy to te ...

  8. Winform MD5

    1:MD5 http://www.cmd5.com/ 字节数组----字符串 //将字节数组中每个元素按照指定的编码格式解析成字符串//直接将数组ToString()//将字节数组中的每个元素ToSt ...

  9. 20151024_003_C#基础知识(File / FileStream / StreamReader/StreamWriter)

    1:绝对路径和相对路径 绝对路径:通过给定的路径直接能在我的电脑中找到这个文件. 相对路径:文件相对于应用程序的路径. 2:编码格式 乱码:产生乱码的原因,就是你保存这个文件所采用的编码,跟你打开这个 ...

  10. bzoj 2809 左偏树\平衡树启发式合并

    首先我们对于一颗树,要选取最多的节点使得代价和不超过m,那么我们可以对于每一个节点维护一个平衡树,平衡树维护代价以及代价的和,那么我们可以在logn的时间内求出这个子树最多选取的节点数,然后对于一个节 ...