Leetcode——04Median of Two Sorted Arrays

来源:互联网 发布:mac国家缩写 编辑:程序博客网 时间:2024/06/05 11:13

本周记录的是一道分治算法的题目,Median of Two Sorted Arrays。

1.题目描述

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

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

简单来说,给出两个有序数列,长度分别为m和n,求出两个有序数列的中值。注意,不是分别求中值,而是两个数列的中值。
举个例子,num1 = [1, 2], num2 = [3, 4], 那么中值是(2+3)/2 = 2.5


2.解题思路


题目要求时间复杂度是在O(log(m+n)),因此,如果是将两个有序数列合并之后,取中值,必然是超时的。因此需要采用其他方法。
考虑一下,两个数列的中值,若m+n是奇数,中值是第m+n+1/2个数,若是偶数,则中值是第m+n/2个数和第(m+n/2)+1个数的平均。
如果我们能使一个数列的长度变为原来的一半,那么计算起来就可能达到O(log(m+n))的复杂度。


举两个数列,数列1是[1,2,3,8,9],数列2是[1,3,5,7,8],先找两个数列的中值,分别是3和5,数列2的中值大于数列1的中值。可以发现,此时,数列1中左半部分[1,2,3]都是小于数列2的中值的。数列1的右半部分大小未知,暂不考虑,说明小于数列2中值的至少有5个数。那么,我们现在要求的中值位置,是k=m+n/2,如果k是小于等于5的,说明数列2的右半部分是属于大值的部分,中值应该是在数列1和数列2的左半部分中得到(因为数列1的右半部分大小是未知的);如果k是大于5的,说明数列1的左半部分是属于小值的部分,中值应该是在数列1的右半部分和数列2中得到。

实际上有点像是使用了寻找第k大的数的算法。只不过是要用在两个数列。好,整理一下,得到一下的算法模型。
记数列1为num1,数列2为num2,数列1的左中右位置分别是l1, mid1, r1,数列2的左中右位置分别是l2, mid2, r2;中值位置k。

findkthNum(nums1, l1, r1, nums2, l2, r2, k)
如果mid1 <= mid2, 则
如果k <= mid1 - l1 + mid2 - l2 + 1,则
findkthNum(nums1, l1, r1, nums2, l2, mid2 - 1, k);                           ①
否则,
findkthNum(nums1, mid1 + 1, r1, nums2, l2, r2, k - (mid1+1-l1));    ②
  否则
如果k <= mid1 - l1 + mid2 - l2 + 1,则
findkthNum(nums1, l1, mid1 - 1, nums2, l2, r2, k);                          ③
否则,
findkthNum(nums1, l1, r1, nums2, mid2 + 1, r2, k - (mid2+1-l2));    ④


这道题思路还是比较容易想到,但是要把思路捋顺,然后实现的话,花了比较多的时间。有一个点是比较难想通的,一是在②这里,为什么num2的左半部分还要进入下一轮。原因是,num1的左半部分是肯定小于num1的右半部分,但是不清楚num1的右半部分和num2的左半部分的大小关系,所以,需要把num2的左半部分加入到下一轮。只要想通了这部分,其他情况都是比较明了的。


3.代码展示

double findkthNum(vector<int>& nums1, int l1, int r1, vector<int>& nums2, int l2, int r2, int k){if(l1 > r1)return nums2[l2 + k - 1];if (l2 > r2)return nums1[l1 + k - 1];int mid1 = (l1 + r1) / 2;int mid2 = (l2 + r2) / 2;if (nums1[mid1] <= nums2[mid2]){if ((mid1 - l1 + mid2 - l2 + 1) >= k)return findkthNum(nums1, l1, r1, nums2, l2, mid2 - 1, k);elsereturn findkthNum(nums1, mid1+1, r1, nums2, l2, r2, k - mid1 + l1 - 1);}else{if ((mid1 - l1 + mid2 - l2 + 1) >= k)return findkthNum(nums1, l1, mid1-1, nums2, l2, r2, k);elsereturn findkthNum(nums1, l1, r1, nums2, mid2+1, r2, k - mid2 + l2 - 1);}}    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {        double result;int k = (nums1.size() + nums2.size() + 1)/2;if((nums1.size() + nums2.size()) % 2 == 0){return (findkthNum(nums1, 0, nums1.size()-1, nums2, 0, nums2.size()-1, k) + findkthNum(nums1, 0, nums1.size()-1, nums2, 0, nums2.size()-1, k+1))/2;}else{return findkthNum(nums1, 0, nums1.size()-1, nums2, 0, nums2.size()-1, k);}return result;    }

总结:题目有点难度,主要是想通这个过程上。可能也是本身做题不够,有时候对这种分治的问题,需要想很久才能捋清思路= =平时还是要多做题啊~~

0 0
原创粉丝点击