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:

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

Example 2:

nums1 = [1, 2]
nums2 = [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:

      left_A             |        right_A
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:

      left_B             |        right_B
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 :

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

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

If we can ensure:

1) len(left_part) == len(right_part)
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) i + j == m - i + n - j (or: m - i + n - j + 1)
if n >= m, we just need to set: i = 0 ~ m, j = (m + n + 1)/2 - i
(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:

Searching i in [0, m], to find an object `i` that:
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> Set imin = 0, imax = m, then start searching in [imin, imax]

<2> Set i = (imin + imax)/2, j = (m + n + 1)/2 - i

<3> Now we have len(left_part)==len(right_part). And there are only 3 situations
that we may encounter:
<a> B[j-1] <= A[i] and A[i-1] <= B[j]
Means we have found the object `i`, so stop searching.
<b> B[j-1] > A[i]
Means A[i] is too small. We must `ajust` i to get `B[j-1] <= A[i]`.
Can we `increase` i?
Yes. Because when i is increased, j will be decreased.
So B[j-1] is decreased and A[i] is increased, and `B[j-1] <= A[i]` may
be satisfied.
Can we `decrease` i?
`No!` Because when i is decreased, j will be increased.
So B[j-1] is increased and A[i] is decreased, and B[j-1] <= A[i] will
be never satisfied.
So we must `increase` i. That is, we must ajust the searching range to
[i+1, imax]. So, set imin = i+1, and goto <2>.
<c> A[i-1] > B[j]
Means A[i-1] is too big. And we must `decrease` i to get `A[i-1]<=B[j]`.
That is, we must ajust the searching range to [imin, i-1].
So, set imax = i-1, and goto <2>.

When the object i is found, the median is:

max(A[i-1], B[j-1]) (when m + n is odd)
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:

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

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

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

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

m <= n, i < m ==> j = (m+n+1)/2 - i > (m+n+1)/2 - m >= (2*m+1)/2 - m >= 0
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中与判断的第一条件即可。

代码:

class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m=nums1.length;
int n=nums2.length;
int[] A=nums1;
int[] B=nums2;
if(m>n){
int temp1=m;
m=n;
n=temp1;
int[] temp2=A;
A=B;
B=temp2;
} int max_left=0;
int min_right=0;
// i+j=m-i+n-j+1
int imin=0,imax=m,half_len=(m+n+1)/2;//出于奇偶的考虑
while(imin<=imax){
int i=(imin+imax)/2;
int j=half_len-i;
if(i<m && B[j-1]>A[i]) imin=i+1;
else if(i>0 && A[i-1]>B[j]) imax=i-1;
else{
       // i is perfect,先求max_left再求max_right
if(i==0){        // A被全部放到了右边
max_left=B[j-1];
}else if(j==0){    // B被全部放到了右边
max_left=A[i-1];
}else{         // 一般情形
max_left=Math.max(A[i-1],B[j-1]);
} if((m+n)%2==1) return max_left; if(i==m){
min_right=B[j];
}else if(j==n){
min_right=A[i];
}else{
min_right=Math.min(A[i],B[j]);
}
return (max_left+min_right)/2.0;
}
}
return -1;
}
}

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. AtCoder Regular Contest 075 E - Meaningful Mean(树状数组)

    题目大意:求一个数组中,平均值不小于k的连续子序列个数 所有数减去k,算个前缀和出来,就变成二维数点问题了. 没有修改,离线的话就是CZL所说的“NOIP最喜欢的套路”了:倒着加进BIT,以权值为数组 ...

  2. bzoj 1131 [POI2008]Sta 树形dp 转移根模板题

    [POI2008]Sta Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1889  Solved: 729[Submit][Status][Discu ...

  3. OopenCV复习及函数深入理解(轮廓查询及绘图)

    核心函数:(后面标明号的,下面有解析) int cvFindContours(Iplimage* img,//这是输入函数,必须是8bit,单通道的图像---1 CvMemStorage* stora ...

  4. Fixed: The Windows Process Activation Service service terminated with the following error: The system cannot find the file specified

    I'm not yet clear what I did, but I'm blogging it so it can be found if someone else has this issue. ...

  5. 读取txt内容放入set中

    package pingbi; /** * 将txt文本读入导入到set中 * 问题: * 第一个地方有会多一个 ?--解决问题很简单,但不知道问题的原因 */ import java.io.Buff ...

  6. 转:Java中的equals和hashCode方法详解

    转自:Java中的equals和hashCode方法详解 Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要重写这 ...

  7. salt总结

    安装jdk jdk: file.managed: - source: salt://service/zabbix/files/jdk1.8.0_121.tar.gz - name: /usr/loca ...

  8. 【BZOJ】4430: [Nwerc2015]Guessing Camels赌骆驼

    [题意]给定三个长度为n的排列,求在三个排列中顺序相同的数对个数. [算法]逆序对 [题解]很容易联想到NOIP火柴排队,涉及顺序问题显然和逆序对息息相关. 一个数对如果在三个排列中顺序不同,一定是1 ...

  9. 【NOIP】提高组2016 天天爱跑步

    [题意]n个点的树,有m个人同时开始走链,每一步花一秒,n个点都有观察员在ai秒观察,求每个观察员观察到的人数. [算法]树上差分(主席树||线段树合并) [题解]一个人的走链可以拆成u-lca和lc ...

  10. Go从入门到精通(持续更新)

    1.0 搭建环境 由于我们 Go官方网站 在我大天朝被和谐了,所以我们只能去 Go语言中文网 来下载了.Go的安装很简单,不像Java还要配置一大堆的东西,选择自己系统的对应版本,下载安装,像安装QQ ...