LeetCode 4. 寻找两个正序数组的中位数***Hard

基本思想:

看到Ologn直接想二分;

这个二分查找不同于查中间值,而是更像是进行部分排除;

对于奇数或者偶数有序序列,查找中位数,相当于查找第k个值;

对于奇数个个数,相当于查找第(n+1)/2个值,而对于偶数个个数,相当于查找第n/2和n/2+1个数字,注意一下,这里下标都是从1开始计数;

对于查找第k个数字,则采用对半查询进行排除;

对于两个序列,分别为m,n大小,并且各自有序;

假设起始坐标都为0,则计算k/2-1,则两个序列的对比范围为: [ 0 , k / 2 − 1 ] [0,k/2-1] [0,k/21]

n u m 1 [ k / 2 − 1 ] > n u m 2 [ k / 2 − 1 ] num1[k/2-1]>num2[k/2-1] num1[k/21]>num2[k/21],则说明num2的前k/2个元素全部小于 n u m 1 [ k / 2 − 1 ] num1[k/2-1] num1[k/21],因此可以将这部分排除;

此时相当于从剩余的部分中寻找第 k − k / 2 k-k/2 kk/2个数,循环至k=1;

之所以循环到k=1,是因为k/2-1=0,此时只需要从两个有序序列的标记索引中二选一即可;

需要注意的地方:

  1. 索引+k/2-1的时候会越界,这里一定要注意;
  2. 如果一个序列遍历完,只需要返回另一个序列的第k个元素即可;

具体代码:

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int total = nums1.size() + nums2.size();
        if (total % 2 == 1) {
            return fun(nums1, nums2, (total + 1) / 2);
        }
        else {
            return (fun(nums1, nums2, total / 2) + fun(nums1, nums2, total / 2 + 1))/2.0;
        }
    }

    double fun(vector<int>& nums1, vector<int>& nums2, int k) {
        int m = nums1.size();
        int n = nums2.size();
        int index1 = 0, index2 = 0;
        while (1) {
            if (m == index1) {
                return nums2[index2 + k - 1];
            }
            if (n == index2) {
                return nums1[index1 + k - 1];
            }
            if (k == 1) {
                return min(nums1[index1], nums2[index2]);
            }
            int newindex1 = min(m - 1, index1 + k / 2 - 1);
            int newindex2 = min(n - 1, index2 + k / 2 - 1);
            if (nums1[newindex1] <= nums2[newindex2]) {
                k -= newindex1 - index1 + 1;
                index1 = newindex1 + 1;
            }
            else {
                k -= newindex2 - index2 + 1;
                index2 = newindex2 + 1;
            }
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值