题目

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

You may assume nums1 and nums2 cannot be both empty.

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

一句话题意,用O(log2(n+m))O(log_2(n+m))O(log2​(n+m))的时间复杂度找出两个数组中的数的中位数。

思路

思路1——直接合并

求中位数说白了就是要找第k大数。

偶数个k有两个取值,奇数k一个取值。

最简单的做法是直接“合并”数组。但是这种做法——

T=O(n+m)M=O(1)T=O(n+m) \quad M = O(1)T=O(n+m)M=O(1)

所以,必然不能合并。

根据复杂度可以猜测是需要用到二分。

思路2——定位两个数组的中间元素,二分

直接定位两个数组的中间元素x和y(下标为数组长度整除2).

示意图如下——

黑色和橙色分别为输入的两个数组。

蓝色是虚拟的两个数组合并后的数组。

每个数组都分为了左右两个长度大致相当的两部分(偶数时相同,奇数时有部分多一个数)。

方框中的字母代表这一部分的第一个元素。



暂时不细致的考虑边界情况,粗略的叙述。

对于x,如果x落在蓝左,则大致可以淘汰黑左,否则可以淘汰黑右.

对于y,如果y落在橙左,则大致可以淘汰橙左,否则可以淘汰橙右.

如此,规模总的缩小为原来的二分之一。

然而,这就需要解决一个问题——

橙色数组中比x小的元素有多少个。

解决了这个问题就可以确定x在蓝色中的位置。

这个问题可以使用二分解决,O(log2m)O(log_2m)O(log2​m)

如此T(n,m)=O(log2m)+O(log2n)+T(n/2,m/2)T(n,m)=O(log_2m)+O(log_2n)+T(n/2,m/2)T(n,m)=O(log2​m)+O(log2​n)+T(n/2,m/2)

这个的复杂度我不会算了,但我估计是超过了O(log2(n+m))O(log_2(n+m))O(log2​(n+m)).

思路3——利用不等式的传递性

在思路2中,我们是用x,y各自淘汰其所在数组的一半元素。

其实是分了两步,而且这两部其实是各自独立,互不相关的。

要达到O(log2(n+m))O(log_2(n+m))O(log2​(n+m))的复杂度,需要我们把问题缩小为原来规模的一半,

但在思路2中我们忽略了不等式的传递性。

为了叙述方便,而且这只是思路,因此下面的不怎么考虑不能除尽、取整的边界问题。



不妨设x<=y(否则可以交换一下两个数组的位置)

因此,可以确定黑左<=x<=y<=蓝右黑左<=黑右

因此两个数组的右半部分都排在黑左的后面,我们黑左里面的排名的上限被确定了,里面的绝大多数元素可以淘汰(之所以不说全部是因为实际上要考虑边界情况)。因此考虑边界情况时,可以往前移动一下(最多移动1格还是2格)。

同理,橙右可以确定排名的下限,然后……

如此,我们O(1)的做到了问题规模缩小一半,复杂度解决了。

然而,个人感觉边界情况讨论起来有点头皮发麻,估计if语句不好写,代码不好写呀。

思路4——为何要两个数组都恰好各自分成相当的两块呢?

思路3中因为分成两半的情况涉及到奇数偶数的差异,两个组合起来情况有点多,我选择死亡。

但是注意到思路3中是利用不等式的传递性来确定排名上下限,而且淘汰掉的两部分刚好是对角的,那么为何不构造一种划分方法,避免边界情况讨论呢?

符号约定

A分成Al,ArA_l,A_rAl​,Ar​两部分,长度分别为la,ral_a,r_ala​,ra​

B分成Bl,BrB_l,B_rBl​,Br​两部分,长度分别为lb,rbl_b,r_blb​,rb​

Al,BlA_l,B_lAl​,Bl​最后一个元素是x1,y1x_1,y_1x1​,y1​

Ar,BrA_r,B_rAr​,Br​第一个元素是x2,y2x_2,y_2x2​,y2​

ala_lal​表示数组AlA_lAl​中任意一个元素,ar,br,cra_r,b_r,c_rar​,br​,cr​同理。

rank(item)rank(item)rank(item)表示itemitemitem在合并后的有序数组的下标(从0计)。

确定限定条件

Ll=la+lb,Lr=ra+rbL_l=l_a+l_b,L_r=r_a+r_bLl​=la​+lb​,Lr​=ra​+rb​

L=n+m=Ll+LrL=n+m=L_l+L_rL=n+m=Ll​+Lr​


  1. 若x2≤2x_2 \leq _2x2​≤2​

    利用不等式的传递性,得:

    rank(al)≤rank(x2)−1=L−Lr−1rank(a_l) \leq rank(x_2)-1 = L-L_r-1rank(al​)≤rank(x2​)−1=L−Lr​−1

    rank(br)≥rank(y2)≥Llrank(b_r) \geq rank(y_2) \geq L_lrank(br​)≥rank(y2​)≥Ll​

    寻找rank为k的元素,欲稳定的可以淘汰Al,BrA_l,B_rAl​,Br​

    ,则需要

    L−1−Lr&lt;kLl&gt;kL-1-L_r \lt k \\
    L_l \gt kL−1−Lr​<kLl​>k

    得Lr&gt;L−1−kLl&gt;kL_r \gt L-1-k \\ L_l&gt;kLr​>L−1−kLl​>k

    另外淘汰数是la+rbl_a+r_bla​+rb​
  2. 若x2≥y2x_2 \geq y_2x2​≥y2​

    同样有:Lr&gt;L−1−kLl&gt;kL_r \gt L-1-k \\ L_l&gt;kLr​>L−1−kLl​>k

    淘汰数是:lb+ral_b+r_alb​+ra​

    为了稳定的将规模缩小为原来的一半,需要

    la+rbl_a+r_bla​+rb​,lb+ral_b+r_alb​+ra​各占总规模的一半。

    不防令

    la+rb=p=L/2lb+ra=L−pl_a+r_b=p=L/2 \\
    l_b+r_a=L-pla​+rb​=p=L/2lb​+ra​=L−p

    上面的公式中出现的除号是整除,不是整除将会使用分号表示,后同

    因此,所有约束条件是:

    ①Lr&gt;L−1−k&ThickSpace;②Ll&gt;k③ra+rb=L/2
    ① L_r \gt L-1-k \; \\
    ② L_l&gt;k \quad \quad \quad \quad \\
    ③ r_a+r_b = L/2 \quad
    ①Lr​>L−1−k②Ll​>k③ra​+rb​=L/2

开始构造

不妨设n&lt;=mn&lt;=mn<=m(否则交换)

取定la∈[0,n]l_a \in [0,n]la​∈[0,n],则

rb=L/2−la=(n+m)/2−la∈[0,m].r_b=L/2-l_a=(n+m)/2-l_a \in [0,m].rb​=L/2−la​=(n+m)/2−la​∈[0,m].

故lal_ala​确定,lb,ra,rbl_b,r_a,r_blb​,ra​,rb​皆确定,且都是在所在数组长度范围内。

Ll=la+lb=la+m−rb=la+m−(n+m)/2+la=2la+m−(n+m)/2L_l = l_a+l_b=l_a+m-r_b \\ =l_a+m-(n+m)/2+l_a \\ =2l_a+m-(n+m)/2 \quad \quad Ll​=la​+lb​=la​+m−rb​=la​+m−(n+m)/2+la​=2la​+m−(n+m)/2

代入②式得:

la&gt;k+(n+m)/2−m2l_a \gt \frac{k+(n+m)/2-m}{2}la​>2k+(n+m)/2−m​

注意k的取值不是任意的,只有(n+m−1)/2(n+m-1)/2(n+m−1)/2与(n+m)/2(n+m)/2(n+m)/2两个取值,总长度相同时这两个取值一样。

  1. 当总长度L为奇数,la&gt;n−12⇒la&gt;(n−1)/2l_a \gt \frac{n-1}{2} \Rightarrow l_a \gt (n-1)/2la​>2n−1​⇒la​>(n−1)/2
  2. 当总长度L为偶数,取前一个数为k,la&gt;n−12⇒la&gt;(n−1)/2l_a \gt \frac{n-1}{2} \Rightarrow l_a \gt (n-1)/2la​>2n−1​⇒la​>(n−1)/2
  3. 当总长度L为偶数,取后一个数为k,la&gt;n2⇒la&gt;n/2l_a \gt \frac{n}{2} \Rightarrow l_a \gt n/2la​>2n​⇒la​>n/2

    由于lal_ala​取值只能是整数,且是大于号,因此上面不等式的右边可以向下取整,可以直接换成整除号。

同理,对于①式的LrL_rLr​,可以得到:

la&lt;k+(n+m)/2−m+12l_a\lt\frac{k+(n+m)/2-m+1}{2}la​<2k+(n+m)/2−m+1​

4. 当总长度L为奇数,la&lt;n2⇒la&lt;(n+1)/2l_a\lt\frac{n}{2} \Rightarrow l_a \lt (n+1)/2la​<2n​⇒la​<(n+1)/2

5. 当总长度L为偶数,取前一个数为k,la&lt;n2⇒la&lt;(n+1)/2l_a \lt \frac{n}{2} \Rightarrow l_a \lt (n+1)/2la​<2n​⇒la​<(n+1)/2

6. 当总长度L为偶数,取后一个数为k,la&lt;n+12⇒la&lt;(n+2)/2l_a \lt \frac{n+1}{2} \Rightarrow l_a \lt (n+2)/2la​<2n+1​⇒la​<(n+2)/2

由于lal_ala​取值只能是整数,且是小于号,因此上面三个式子的右边的数应该向上取整,可以分子加1再整除。

但是,目前很不幸的发现,lal_ala​的上界和下界是相邻的两个整数,而且两不等号个都是不带等于的不等号,因此,lal_ala​可取的值是空集。

小于号换成小于于等于,即①式变成小于等于,一路追溯上去,只需要不淘汰x1x_1x1​(或y1y_1y1​)即可。

那么lal_ala​的取值:

la=n/2+1总长度偶数,且k取后一个数l_a=n/2+1 总长度偶数,且k取后一个数la​=n/2+1总长度偶数,且k取后一个数

其余情况la=(n+1)/2l_a=(n+1)/2la​=(n+1)/2

因排名小于k被淘汰掉的个数为la−1l_a-1la​−1,故k−=la−1k-=l_a-1k−=la​−1

代码什么的下次再写

我现在发现求出来的结果和原本的直接两个数组两两对半分差别不大,心态有点崩。而且貌似这样子递归之后k就不是原本的总长度的一半了……

emmmm…

先O(n)暴力通过吧,另外膜拜一下discussion里的dalao解法

O(N)源码

class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int l1 = nums1.length;
int l2 = nums2.length;
int l = l1 + l2;
int nums[] = new int[l];
int end = l/2+1;
int i,j,k;
i = j = k = 0;
while (i < l1 && j < l2 && k < end) {
if (nums1[i] < nums2[j])
nums[k++] = nums1[i++];
else
nums[k++] = nums2[j++];
}
while (i < l1 && k < end)
nums[k++] = nums1[i++];
while (j < l2 && k < end)
nums[k++] = nums2[j++];
if (l%2 == 0)
return (nums[l/2-1]+nums[l/2])/2.0;
else
return nums[l/2];
}
}

Runtime: 26 ms, faster than 91.16% of Java online submissions for Median of Two Sorted Arrays.

Memory Usage: 49.7 MB, less than 100.00% of Java online submissions for Median of Two Sorted Arrays.

下次有时间在用discuss里面dalao的方法写一次。

LeetCode 第四题 Median of Two Sorted Arrays 二人 渣渣选手乱七八糟分析发现基本回到思路1的更多相关文章

  1. leetcode 第4题 Median of Two Sorted Arrays

    class Solution { public: double findMedianSortedArrays(vector<int>& nums1, vector<int&g ...

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

  3. 【LeetCode】4、Median of Two Sorted Arrays

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

  4. 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 the ...

  5. 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 the two ...

  6. LeetCode 笔记系列一 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 sort ...

  7. LeetCode 4 Median of Two Sorted Arrays (两个数组的mid值)

    题目来源:https://leetcode.com/problems/median-of-two-sorted-arrays/ There are two sorted arrays nums1 an ...

  8. 【转载】两个排序数组的中位数 / 第K大元素(Median of Two Sorted Arrays)

    转自 http://blog.csdn.net/zxzxy1988/article/details/8587244 给定两个已经排序好的数组(可能为空),找到两者所有元素中第k大的元素.另外一种更加具 ...

  9. 4. Median of Two Sorted Arrays(topK-logk)

    4. Median of Two Sorted Arrays 题目 There are two sorted arrays nums1 and nums2 of size m and n respec ...

随机推荐

  1. Cacti 安装插件

            Cacti本身可以以图形化界面显示出流量状态,cacti也可以安装插件,通过插件,cacti的功能被进一步强大:可以监控服务器状态:发送邮件通知:短信通知等.        0.88之 ...

  2. [Redis-CentOS7]Python操作Redis(十一)

    Python 操作redis #!/usr/bin/env pyhton # coding:utf-8 # @Time : 2020-02-16 21:36 # @Author : LeoShi # ...

  3. Admin后台权限管理、三大认证

    目录 APIView的请求生命周期 三大认证规则 权限六表 自定义User表 详细配置演示 models.py setting.py admin.py 使用过程: 控制填写信息的字段 控制添加权限 控 ...

  4. 在Windows系统中安装Redis和php_redis扩展

    安装Redis (1)下载redis压缩包,git下载地址https://github.com/MSOpenTech/redis/releases 解压文件夹,在文件夹中运行cmd命令: 输入:   ...

  5. git报错:fatal: No configured push destination.

    本地仓库代码(git push)上传git仓库报错: fatal: No configured push destination. Either specify the URL from the co ...

  6. mysql出现 Unknown column 'Password' in 'field list'

    linux安装了mysql之后初始化密码获取:出现了下面的内容,密码很尴尬,无法用root登录: grep 'temporary password' /var/log/mysqld.log [Note ...

  7. java数据结构---循环队列

    #java学习经验总结------循环队列的实现(数组) package datastructure;/*数组实现循环队列 队列first in first out*/ public class Ci ...

  8. 笔记本磁盘中OEM分区的使用

    (1).开机进入系统前,按F8,进入Windows 10的高级启动选项,选择“修复计算机”. (2).选择键盘输入方法. (3).如果有管理员密码,需要输入:如果没有设置密码,直接“确定”即可. (4 ...

  9. P3884 [JLOI2009]二叉树问题

    --------------------- 链接:Miku --------------------- 这一道题只需要在倍增lca的板子上改一改就可以了. 宽度和深度可以在倍增lca的dfs预处理的时 ...

  10. 9.16java总结

    枚举   EnunTest.java 运行结果 falsefalsetrueSMALLMEDIUMLARGE 枚举类型可以直接用==来判断是否相等,即代表数据串,又有数的属性.是引用类型. 浮点数计算 ...