题目
4. Median of Two Sorted Arrays
- Difficulty: Hard
- Total Accepted: 301.7K
- Total Submissions: 1.3M
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.
Example1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Exaple2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
解题报告
AC 截图
题目大意
本题要求寻找两个有序序列合并后的序列的「中位数」。同时要求 O(log (m+n)) 级别的时间复杂度。
解题思路
在一个序列中寻找一个数,又要求 O(log) 级的时间复杂度,我们很容易想到通过不断分割区间来寻找目标数的二分查找法。那么唯一的问题是如何在两个有序序列上应用针对单条序列的二分查找法了。
创建变量 start1
、end1
、start2
、end2
、halfSize
,分别标识两个序列当前处理区间的头和尾,以及用于计数左侧较小数个数。通过不断对比两个区间中间数的大小,来使得中间数靠近,直到 halfSize
达到序列长度的一半即可(题解中为从一半减少到1)。
题解1
C++ 代码
1 | class Solution { |
AC 截图
题解分析
虽然这个题解顺利通过了测试,但是我们发现,前面的最优解还有相当多……那么尝试对于代码进行优化。我们知道,递归方法相对于迭代法需要在每次递归时,对栈进行单独的操作——在空间和时间复杂度上都不如迭代法。
那么,是否可以把递归法转换为迭代法呢——当然可以啦~
题解2
C++ 代码
1 | class Solution { |
AC 截图
题解分析
嗯?这两个的耗时完全没有区别啊!看来是编译器已经把我的递归优化掉了……那么和第一梯队如此大的时间差又是从何而来呢?
参加过 ACM 的同学应该都知道,能用 scanf
的代码绝对不用 cin
。不过其实 cin
的效率并不算差,只是,我们需要对其进行一些优化才能让他发挥出应有的实力。要想解放 cin
实力的封印,一行代码足矣:
ios::sync_with_stdio(false);
这会禁用 cin/cout 和 scanf/printf 之间的同步等待,从而大幅提升 cin 的效率——甚至可以直追 scanf。但是这里我们又有一个问题了,我们函数的调用显然是在输入操作之后,怎样才能让这个函数在输入操作前生效呢?当然是有办法的啦:
题解3(最优解)
C++ 代码
1 | static const auto runfirst = []() { |
AC 截图
题解分析
通过声明一个静态的常量变量,我们使得后面这个自执行的函数甚至可以在编译阶段预执行,从而在输入输出前完成对于 cin/cout 的设置~总时耗也从 56ms 下降到了 16ms,妥妥的第一梯队~看来算法和实现细节都是保证程序执行速度的重要环节呢。