LeetCode.4 两个有序数组的中位数问题
2016-11-16 02:33
141 查看
这道题是那种典型的有显而易见的解法, 但是想要达到较优的时间复杂度的话就不是这么好做的题目.
我来说说我自己的思考过程 :
首先最先想到的是 O(m + n) 的解法, 也就是利用归并排序的归并将两个数组合成一个.
然后题目中要求的时间复杂度是 O(log (m + n)), 想到log自然就想到了分制之类的东西, 也就是通过用常数级别的操作来减小问题规模来求解.
其实算法导论里面有类似的题目, 当时觉得简单就没有实现, 基本思路是 : 尝试着通过不断地比较两个数组的中值来舍弃掉一些元素(就是说我们可以判断出整体中值一定是会出现在两个中值之间的, 包括边界). 于是我开始依照这种思路来进行代码的实现.
然后我碰到了如下问题 :
1. 没有考虑一开始输出的两个数组都为空的corner case.
2. 舍弃一部分元素时将中值舍去, 其实整体中值极有可能是两个中值求平均数, 也就是我上面提到的整体中值极有可能出现在两个中值之间.
3. 当较小的数组下降到2的时候, 此时必须开始求解, 因为无法舍弃更多的元素.(但是事实上, 这时候开始求解, 如果使用不插入的话, 其实情况很多, 讨论起来特别费劲)
经过了一天的尝试, 最后我放弃了这种做法. 我开始在网上寻找新的解法, 最后我觉得最好的解法是 : LeetCode 笔记系列一 Median of Two Sorted Arrays.
不过他上面的代码并不符合leetcode上提供的接口, 所以我自己给出了以下实现 :
我来说说我自己的思考过程 :
首先最先想到的是 O(m + n) 的解法, 也就是利用归并排序的归并将两个数组合成一个.
然后题目中要求的时间复杂度是 O(log (m + n)), 想到log自然就想到了分制之类的东西, 也就是通过用常数级别的操作来减小问题规模来求解.
其实算法导论里面有类似的题目, 当时觉得简单就没有实现, 基本思路是 : 尝试着通过不断地比较两个数组的中值来舍弃掉一些元素(就是说我们可以判断出整体中值一定是会出现在两个中值之间的, 包括边界). 于是我开始依照这种思路来进行代码的实现.
然后我碰到了如下问题 :
1. 没有考虑一开始输出的两个数组都为空的corner case.
2. 舍弃一部分元素时将中值舍去, 其实整体中值极有可能是两个中值求平均数, 也就是我上面提到的整体中值极有可能出现在两个中值之间.
3. 当较小的数组下降到2的时候, 此时必须开始求解, 因为无法舍弃更多的元素.(但是事实上, 这时候开始求解, 如果使用不插入的话, 其实情况很多, 讨论起来特别费劲)
经过了一天的尝试, 最后我放弃了这种做法. 我开始在网上寻找新的解法, 最后我觉得最好的解法是 : LeetCode 笔记系列一 Median of Two Sorted Arrays.
不过他上面的代码并不符合leetcode上提供的接口, 所以我自己给出了以下实现 :
#include <vector> using namespace std; class Solution { public: double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { auto size = nums1.size() + nums2.size(); if(size % 2 == 0){ return (findKth(nums1.cbegin(), nums1.cend(), nums2.cbegin(), nums2.cend(), size / 2 + 1) + findKth(nums1.cbegin(), nums1.cend(), nums2.cbegin(), nums2.cend(), size / 2)) / 2; }else{ return findKth(nums1.cbegin(), nums1.cend(), nums2.cbegin(), nums2.cend(), size / 2 + 1); } } private: double findKth(vector<int>::const_iterator n1Start, vector<int>::const_iterator n1End, vector<int>::const_iterator n2Start, vector<int>::const_iterator n2End, long k){ // make sure size1 >= size2 auto size1 = n1End - n1Start; auto size2 = n2End - n2Start; if(size1 < size2) return findKth(n2Start, n2End, n1Start, n1End, k); if(size1 == 0) return 0; if(size2 == 0) return n1Start[k - 1]; if(k == 1) return std::min(n1Start[0], n2Start[0]); long p2 = std::min(size2, k / 2); long p1 = k - p2; if(n1Start[p1 - 1] >= n2Start[p2 - 1]){ k = p1; n2Start += p2; } else{ k = p2; n1Start += p1; } return findKth(n1Start, n1End, n2Start, n2End, k); } };
相关文章推荐
- 【分步详解】两个有序数组中的中位数和Top K问题
- 两个有序数组中的中位数和Top K问题(深度好文)
- 求两个等长有序数组中位数算法问题
- (分治算法)两个有序数组中的中位数和Top K问题
- 【分步详解】两个有序数组中的中位数和Top K问题
- google笔试题两个n维数组logn求中位数问题 zz
- 给定两个有序的n长度的数组,如何找出这两个数组合并后的中位数?
- 求两个有序数组的中位数
- 寻找两个数组的中位数 Median of Two Sorted Arrays ***问题转化思想***
- 两个等长有序数组求中位数
- 求两个不等长的有序数组的中位数
- 求解两个有序数组的中位数
- 求两个有序数组的中位数
- 两个有序数组的中位数 Median of Two Sorted Arrays
- 两个有序数组合并,并求中位数(复杂度为O(m+n))
- 给定两个长度相同,分别有序的数组A和B,求两个数组中所有数的中位数
- 求两个有序数组的中位数
- 有序数组求中位数问题
- 关于在一个序列中寻找中位数和第K大的数(在两个等长有序数组中寻找中位数)
- 求两个等长有序数组的中位数的logN算法 分治法