LeetCode 4. 寻找两个有序数组的中位数(难)
折半查找(二分查找)的时间复杂度是 \(O(log_2\ n)\),也就是 \(O(log\ n)\)。
题目
给定两个大小为 m 和 n 的有序数组 nums1
和 nums2
。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m+n))。
你可以假设 nums1
和 nums2
不会同时为空。
示例
示例一 1
2
3
4
5nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:1
2
3
4nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
考察知识点
折半查找、边界判定、无尾递归
核心思想
将两个有序数组重组,求中位数。 将问题 转化为在两个数组中找第 K 个小的数 。 求中位数,其实就是求第 k
小数的一种特殊情况。 首先在两个数组中分别找出第k/2
大的数,再比较这两个第 k/2
大的数,这里假设两个数组为 A ,B。 那么比较结果会有下面几种情况: - A[k/2] = B[k/2],那么第 k 大的数就是 A[k/2] - A[k/2] > B[k/2],那么第 k 大的数肯定在 A[0:k/2+1] 和 B[k/2:] 中,这样就将原来的所有数的总和减少到一半了,再在这个范围里面找第 k/2 大的数即可,这样也达到了二分查找的区别了。 - A[k/2] < B[k/2],那么第 k 大的数肯定在 B[0:k/2+1]和 A[k/2:] 中,同理在这个范围找第 k/2 大的数就可以了。 反复递归执行上述过程即可
Python版本
不满足算法复杂度的一个版本
1 |
|
满足O(log(m+n))复杂度的一个算法
1 |
|
- 上述算法的时空复杂度分析
时间复杂度:每进行一次循环,减少 k/2 个元素,所以时间复杂度是 O(log(k),而 k = (m+n) / 2,所以最终的复杂也就是 O(log(m+n)。
空间复杂度:虽然用到了递归,但是可以看到这个递归属于尾递归(见通用算法知识),所以编译器不需要不停地堆栈,所以空间复杂度为 O(1)。
有效语法糖
1、python3的range函数实现从后往前循环
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!