题干:给定两个大小分别为 m
和 n
的正序(从小到大)数组 nums1
和 nums2
。请你找出并返回这两个正序数组的 中位数 。
一、题目分析
考察序列的中位数存在特点。一般情况下对于奇数长度排好序的序列 x 1 , x 2 , x 3 ⋯ x n x_1,x_2,x_3\cdots x_n x1,x2,x3⋯xn其中位数 x m i d x_{mid} xmid满足下列的条件:
- ∀ n > m i d , x n > x m i d \forall n>mid,x_n > x_{mid} ∀n>mid,xn>xmid
- ∀ n < m i d , x n < x m i d \forall n<mid,x_n <x_{mid} ∀n<mid,xn<xmid
在这样的意义下该序列可被其中位数分成两个不相交的集合。对于这两个升序数组而言,假定根据中位数的存在位置
- 若 ( m + n ) % 2 = 0 (m+n)\%2 =0 (m+n)%2=0,则将两个数组归并升序排好的数组前一半归结到第一个集合中,后一半归结到第二个集合中
- 否则将归并排序升序排的数组根据中位数,左边的位于第一个集合中,右边的位于第二个集合中,该中位数位于第一个集合中
将其分成两个不相交的集合(设这两个数组分别为A和B,数组长度分别为m和n)
- A [ 0 ] , A [ 1 ] ⋯ A [ i − 1 ] , B [ 0 ] , B [ 1 ] ⋯ B [ j − 1 ] A[0],A[1]\cdots A[i-1],B[0],B[1]\cdots B[j-1] A[0],A[1]⋯A[i−1],B[0],B[1]⋯B[j−1]
- A [ i ] , A [ i + 1 ] ⋯ A [ m − 1 ] , B [ j ] , B [ j + 1 ] ⋯ B [ n − 1 ] A[i],A[i+1]\cdots A[m-1],B[j],B[j+1]\cdots B[n-1] A[i],A[i+1]⋯A[m−1],B[j],B[j+1]⋯B[n−1]
该两个集合满足下列的条件:
- m a x { A [ i − 1 ] , B [ j − 1 ] } ≤ m i n { A [ i ] , B [ j ] } max\{A[i-1],B[j-1]\} \leq min\{A[i],B[j]\} max{A[i−1],B[j−1]}≤min{A[i],B[j]}
- 对于m+n为奇数而言,有 i + j = m − i + n − j + 1 i+j =m-i+n-j+1 i+j=m−i+n−j+1,亦即 j = m + n + 1 2 − i j=\frac{m+n+1}{2}-i j=2m+n+1−i
- 对于m+n为偶数而言,有
i
+
j
=
m
−
i
+
n
−
j
i+j = m-i+n-j
i+j=m−i+n−j,亦即
j
=
m
+
n
2
−
i
j = \frac{m+n}{2}-i
j=2m+n−i.在高级语言JAVA中下列代码具有等价的形式
j = (m+n+1)/2 - i
和j = (m+n)/2-i
即如j是整型那么将忽略小数部分。因此在这样的意义下,也可以写成 j = m + n + 1 2 − i j=\frac{m+n+1}{2}-i j=2m+n+1−i的形式。
命题: 在一般情形下,给定i值,利用公式 j = m + n + 1 2 − i j = \frac{m+n+1}{2} - i j=2m+n+1−i计算出j值。如果i和j能够使得下述式子成立: m a x { A [ i − 1 ] , B [ j − 1 ] } ≤ m i n { A [ i ] , B [ j ] } max\{A[i-1],B[j-1]\} \leq min\{A[i],B[j]\} max{A[i−1],B[j−1]}≤min{A[i],B[j]}那么就有下面的结论成立:
- 如果m+n为偶数,那么中位数 x m i d = m a x { A [ i − 1 ] , B [ j − 1 ] } + m i n { A [ i ] , B [ j ] } 2 x_{mid} = \frac{max\{A[i-1],B[j-1]\}+min\{A[i],B[j]\}}{2} xmid=2max{A[i−1],B[j−1]}+min{A[i],B[j]}
- 如果m+n为奇数,那么中位数 x m i d = m a x { A [ i − 1 ] , B [ j − 1 ] } x_{mid} = max\{A[i-1],B[j-1]\} xmid=max{A[i−1],B[j−1]}
证明: 对于一个给定的i,由于由上述公式确定j,因为上述公式实际上是等价于
i
+
j
=
(
m
+
n
+
1
)
2
i+j = \frac{(m+n+1)}{2}
i+j=2(m+n+1),且有上述命题中的第二个式子成立,所以可以确定集合划分:
- A [ 0 ] , A [ 1 ] ⋯ A [ i − 1 ] , B [ 0 ] , B [ 1 ] ⋯ B [ j − 1 ] A[0],A[1]\cdots A[i-1],B[0],B[1]\cdots B[j-1] A[0],A[1]⋯A[i−1],B[0],B[1]⋯B[j−1]
- A [ i ] , A [ i + 1 ] ⋯ A [ m − 1 ] , B [ j ] , B [ j + 1 ] ⋯ B [ n − 1 ] A[i],A[i+1]\cdots A[m-1],B[j],B[j+1]\cdots B[n-1] A[i],A[i+1]⋯A[m−1],B[j],B[j+1]⋯B[n−1]
满足第一个集合中的元素小于等于第二个集合中的元素,并且上面集合中的元素个数为 ( m + n + 1 ) 2 \frac{(m+n+1)}{2} 2(m+n+1),下面集合中的元素个数为总个数相减。因此对于总长度为奇数长度而言,中位数就是第一个集合中的最大值,在 A [ i − 1 ] A[i-1] A[i−1]和 B [ j − 1 ] B[j-1] B[j−1]中进行产生。对于总长度为偶数而言,两个集合的长度是相同的(注意高级语言JAVA中\的运算实际上是要取整的),因此中位数就是第一个集合中的最大值和第二个集合中的最小值的平均值。证毕。
式子
m
a
x
{
A
[
i
−
1
]
,
B
[
j
−
1
]
}
≤
m
i
n
{
A
[
i
]
,
B
[
j
]
}
max\{A[i-1],B[j-1]\} \leq min\{A[i],B[j]\}
max{A[i−1],B[j−1]}≤min{A[i],B[j]}的等价形式为
A
[
i
−
1
]
≤
B
[
j
]
&
&
B
[
j
−
1
]
≤
A
[
i
]
A[i-1] \leq B[j] \&\& B[j-1]\leq A[i]
A[i−1]≤B[j]&&B[j−1]≤A[i]这是因为原先数组是递增的。
至此,上述分析已经给出了一个算法了。即枚举i,根据公式确定j,如果满足上述式子的等价形式,那么就按照上述命题的思路确定中位数。还有一个命题可以进一步指导优化算法:
命题: 满足
A
[
i
−
1
]
≤
B
[
j
]
A[i-1]\leq B[j]
A[i−1]≤B[j]的最大的i值一定满足
B
[
j
−
1
]
≤
A
[
i
]
B[j-1]\leq A[i]
B[j−1]≤A[i]
证明: 若不然则
B
[
j
−
1
]
>
A
[
i
]
B[j-1]> A[i]
B[j−1]>A[i],注意j的确定由式子
j
=
m
+
n
+
1
2
−
i
j = \frac{m+n+1}{2} - i
j=2m+n+1−i,即i+1也满足条件,与i是最大的矛盾。