给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n))
题目出自LeeCode
观察时间复杂度就知道使用的方法应该是二分查找,并且对有序数组进行分块处理
分别是:1、两个数组的元素个数都是偶数
2、两个数组的元素个数都是奇数
3、两个数组的元素个数一奇一偶
关于处理的方法:
对于两个数组,分别求取中间位置的数,实现第一次二分查找,得到两条分界线,第一个数组分界线左边的数严格小于分界线右边的数,第二组数字同理;
然后对“第一组数字分界线左边与第二组数字分界线右边” 和 “第二组数字分界线左边与第一组数字分界线右边” 这两组数字进行比较;
然后对两条分界线进行左移和右移,最终使得两条分界线形成的总分界线左边的数字严格小于分界线右边的数字,实现对两个数组的合并和排序,最终取得中位数。
说明:
以下内容还未封装成函数形式,只是呈现思路和方法,并且不是最简单最快捷的方法,在DevC++中 F11运行平均用时0.16秒,给各位造成阅读上的不便利还请见谅,如果有知识上的错误,望斧正。
第一种情况:以图片中的两个数组为例
考虑到第一个数组 a 分界线右一个元素小于第二个数组 b 分界线左边一个元素,总分界线调整为:a分界线右移,b分界线左移
同理另外一种情况
分界线移动方向恰好相反
最终得到总分界线左边的最大值 和 分界线右边的最小值 ,这两个就是两个有序数组排序之后处在中间位置的两个运算参数,最终用 float计算即可。
第一幅图片中给出来的是恰好分界线就是总分界线的情况,不需要移动分界线。
第二种情况:两个数组元素个数都是奇数
a[ ]={2,3,4, | 6,8} ;
b[ ]={1,3,4,6, | 7,8,9,11,13} ; 以此为例 其中的 | 是假想的分界线
一个数组多分一个,一个数组少分一个,涉及到整数的除法的时候,其中一个数组的mid加一即可。
这里对 m 数组进行了分界线调整
我还对数组的长度进行了分类,可以说是不太必要,只是为了看上去好看一些,做题习惯罢了,这里就不做展示了。
同理,另一种情况也是相反的调整过程
第三种:两个数组元素个数一奇一偶,算是最简单的一种情况,因为不涉及到运算,找到即输出。我同样按照数组元素个数进行了不同的讨论,大同小异
这里展示其中一种情况:
还有一些特殊情况:
当其中一组数字全部严格小于另一组数字的时候,总分界线移动到数组的边界,对于判断的时候的<>=这三个符号的使用需要反复思考和斟酌。防止数组访问下标越界。
总结:
我的方法,不太适合在面试的时候手撕,权当作是提供一种不太聪明的暴力思路。运行速度还算ok,但是内存占用绝对是爆表。感谢你阅读到这里。如有错误,望指正!