【leetCode】之Median of Two Sorted Arrays

参考博客:https://blog.csdn.net/xu2645318400/article/details/73924591

题目:

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.

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

分析:同样卡了我好久的题。。。

题目大意就是求两个升序序列的中位数(中位数:若奇数序列为中间的元素值,偶数序列为中间两个元素的均值~)

这题要求了时间复杂度O(log(m+n)),看到这种时间复杂度想到的方法就应该是二分法,当然想起了王道上的一道求两等长升序序列S1,S2中位数的题,当时的做法是每次淘汰S1中的一半元素与S2中的一半元素,当然要保证每次S1 S2淘汰的元素个数是相同的,多了不赘述,回归本题。。。

由于本题是不等长的两个升序序列,而且还存在其中一个数组为空的情况,考虑方法就有所不同。将本题的求中位数转换成求两序列排序后的第k(k = 两数组长度和加一 / 2)个数,也就是中位数所在的位置,但是中位数有的时候是两数的均值,那么第一个数的位置为两数组长度和加一/2,第二个数的位置为多少?答案是 两数组长度和加二/2(可以自行检测)当两数组长度和为奇数的时候以上的两数值相同,为偶数的时候两数值差一,所以中位数=(两数组长度和加一/2 个元素+ 两数组长度和加二/2个元素)/ 2

思路

二分法,每次尽量排除一个数组中的前一半比较小的元素,递归。。

分治法,对每次排除元素时采取不同的动作

递归边界

1、其中一个数组为空或元素均已淘汰

       if(low1 == m)   //nums1数组为空或者说元素都已排除
            return nums2[low2 + k - 1] ;
        if(low2 == n)  //nums2数组为空或者说元素都已排除
            return nums1[low1 + k - 1] ;
  2、若查找第k个元素,k为1 或者是已递归至1

        if(k == 1)   //要找两数组中的第一个元素,则返回两数组中最小的元素
             return nums1[low1]<nums2[low2] ? nums1[low1] : nums2[low2] ;

递归条件

1、保证其中一个数组短,防止溢出访问(比如要取第k / 2个元素时,有一个数组的长度小于k / 2,那么就访问溢出了,踩坑的我。。。),解决办法就是让每次淘汰的元素等于min(最短的数组,k/2)

p1代表短数组能淘汰的元素个数,即 p1= min(最短的数组,k/2)

p2代表长数组能淘汰的元素个数,并保证每次淘汰k/2个元素,所以 p2 = k/2 - p1

2、nums1[low1 + p1 - 1] < nums2[low2 + p2 - 1],更新low值与k值

由于每次淘汰的是前面比较小的数,所以数组的起始位置未必是0

low值就是用来记录数组起始位置的元素

3、nums1[low1 + p1 - 1] <= nums2[low2 + p2 - 1],更新low值与k值

代码:

​
class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        
        int low1 = 0 , low2 = 0 , m = nums1.size() , n = nums2.size() , k = (m + n + 1) / 2 ;
        double res ;
        
        res = getMedian(nums1, nums2, low1, m, low2, n, k);
        res += getMedian(nums1, nums2, low1, m, low2, n, (m + n + 2) / 2);
        
        return res / 2 ;
        
    }
    
    int getMedian(vector<int>& nums1, vector<int>& nums2, int low1, int m, int low2, int n, int k){
        if(low1 == m)
            return nums2[low2 + k - 1] ;
        if(low2 == n)
            return nums1[low1 + k - 1] ;
        if(k == 1)
            return nums1[low1]<nums2[low2] ? nums1[low1] : nums2[low2] ;
        if(m - low1 > n - low2)
            return getMedian(nums2, nums1, low2, n, low1, m, k);
        
        int p1 = (m - low1) < k / 2 ? m - low1 : k / 2 ;
        int p2 = k - p1 ;
        
        if(nums1[low1 + p1 - 1] < nums2[low2 + p2 - 1]){
            low1 += p1 ;
            k -= p1 ;
        }
        else{
            low2 += p2 ;
            k-= p2 ;
        }
        return getMedian(nums1, nums2, low1, m, low2, n, k);
    }
};

​

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值