【LeetCode热题100】【二分查找】寻找两个正序数组的中位数

题目链接:4. 寻找两个正序数组的中位数 - 力扣(LeetCode)

在两个有序数组中在不合并的前提下寻找他们合并后的中位数,这个可以转换成寻找第k大的数

我们来看看这个第k大的数应该在什么地方,下标从0开始,那么ai前面有i个数,bj前面有j个数

那么如果i+j=k,那么说明ai和bj前面有k个数,如果ai-1<=bj并且bj-1<=ai,这就说明这k个数就是合并后有序的前k个数,那么第k大的数就是ai-1和bj-1之间的较大者

所以可以在a中二分查找符合条件的i,让j=k-i,如果bj-1>ai说明i的位置应该往后挪查找,否则往前查找

这里需要注意j的范围,因为bj-1和bj可以不存在,比如a=123,b=456,如果要找3,那么i=3,j=0,此时bi-1是不存在的,ai也是不存在的,因此0<=j<=m,即0<=k-i<=m,即i<=k,i>=k-m

这样可以二分确定第k大的范围,那么要找中位数,如果总长度是偶数,那么中位数就是中间两个数的平均值,否则就是中间那个数

复制代码
class Solution {
public:
    int findK(vector<int> &nums1, vector<int> &nums2, int k) {
        int left = max(0, int(k - nums2.size())), right = min(k, int(nums1.size()));
        while (left < right) {
            int mid = (left + right) / 2;
            if (nums2[k - mid - 1] > nums1[mid])
                left = mid + 1;
            else
                right = mid;
        }
        return max(left ? nums1[left - 1] : INT_MIN, k - left ? nums2[k - left - 1] : INT_MIN);
    }

    double findMedianSortedArrays(vector<int> &nums1, vector<int> &nums2) {
        int mn = nums1.size() + nums2.size();
        if (mn & 1)
            return findK(nums1, nums2, mn / 2 + 1);
        return (findK(nums1, nums2, mn / 2) + findK(nums1, nums2, mn / 2 + 1)) / 2.0;
    }
};
相关推荐
papership6 小时前
入门级-数据结构-2、简单树:二叉树的遍历(前序、中序、后序)
数据结构·算法
WWW65266 小时前
代码随想录 打卡第五十四天
数据结构·c++·算法
happymaker06266 小时前
LeetCodeHot100——15.三数之和
数据结构·算法
墨白曦煜6 小时前
算法实战笔记:空间换时间的黑魔法——单调栈全景解析(十一)
java·笔记·算法
大模型最新论文6 小时前
小红书提出 RedKnot:分头处理 kv 缓存,延时降低 60%效果还提升
算法
随意起个昵称6 小时前
线性dp-LIS题目6(友好城市,二分优化)
算法·动态规划
数据科学小丫6 小时前
算法:随机森林算法
算法·随机森林·机器学习
Samson Bruce6 小时前
【初高中数学】
线性代数·数学·算法·机器学习
redaijufeng6 小时前
我在C++中深入理解了继承,收获颇丰
java·c++·算法
承渊政道6 小时前
【MySQL数据库学习】MySQL基本查询(下)
数据库·学习·mysql·leetcode·bash·数据库开发·数据库系统