Leetcode热门100之寻找两个正序数组的中位数

题目描述:

给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。

请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例:

nums1 = [1, 3]
nums2 = [2]

则中位数是 2.0
nums1 = [1, 2]
nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

代码:

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int l1 = nums1.size();
        int l2 = nums2.size();
        int l = l1 + l2;
        int i = 0, j = 0;
        int median = l / 2;
        int cnt = 0;
        int now = 0;
        int left, right;
        while(i < l1 || j < l2){
            if(cnt == median){
                left = now;
            }
            else if(cnt == median+1){
                right = now;
                break;
            }
            if(i == l1)
                now = nums2[j++];
            else if(j == l2)
                now = nums1[i++];
            else if(nums1[i]<nums2[j])
                now = nums1[i++];
            else if(nums1[i]>nums2[j])
                now = nums2[j++];
            cnt++;
        }
        if(l%2)
            return (double)right;
        else return (double)(left + right)/2;
    }
};

归并排序的思路,本来用了一个数组保存排序结果,后来看了一篇题解反应过来并不需要,两个数组长度已知中位的位置就是固定的,只要找到那个位置的数即可。

虽然通过了,其实并未达到要求的时间复杂度,看官方题解,要想达到log的时间复杂度,二分是个正确的选择。

 

二分思路:

由于数组长度已知,求中位数可化解为求第k小的数,每次去掉k/2个数。

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int l1 = nums1.size();
        int l2 = nums2.size();
        int k1 = (l1 + l2 + 1)/2;
        int k2 = (l1 + l2 + 2)/2;
        return (get_kth(nums1, 0, l1-1, nums2, 0, l2-1, k1) + get_kth(nums1, 0, l1-1, nums2, 0, l2-1, k2)) /2;
    }
    
    double get_kth(vector<int>& nums1, int begin1, int end1, vector<int>& nums2, int begin2, int end2, int k){
        int l1 = end1 - begin1 + 1;
        int l2 = end2 - begin2 + 1;
        if(l1 > l2)//确保如果有数组空了一定是第一个
            return get_kth(nums2, begin2, end2, nums1, begin1, end1, k);
        
        //两种情况,如果其中一个数组空了,直接返回另一数组的第k个值
        //如果k=1,比较两个数组的头值并返回较小的那个
        if(l1 == 0) return nums2[begin2+k-1];
        if(k == 1) return min(nums1[begin1], nums2[begin2]);

        int i = min(end1, begin1+k/2-1);
        int j = min(end2, begin2+k/2-1);
        int n1 = nums1[i];
        int n2 = nums2[j];
        
        if(n1 < n2)
            return get_kth(nums1, i+1, end1, nums2, begin2, end2, k-i+begin1-1);
        else return get_kth(nums1, begin1, end1, nums2, j+1, end2, k-j+begin2-1);
            
    }
};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值