当前位置: 首页 > news >正文

LeetCode 第4题:寻找两个正序数组的中位数

题目描述

给定两个大小分别为m和n的正序数组(从小到大)数组nums1和nums2。请你找出并返回这两个正序数组的中位数。要求算法的时间复杂度应该为O(log(m+n))。

难度:困难

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

示例一:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2

 示例二:

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

提示:

  • nums1.length == m
  • nums2.length == n
  • 0 <= m <= 1000
  • 0 <= n <= 1000
  • 1 <= m + n <= 2000
  • -106 <= nums1[i], nums2[i] <= 106

解题思路:

方法一:二分查找

该题最关键的地方在于时间复杂度要达到O(log(m+n)),故必须使用二分查找,将该问题转化为寻找第k小数的问题。

注意点:

  • 中位数的定义
  1. 当总长度为奇数时,中位数是第(m+n)/2+1个数。
  2. 当总长度为偶数时,中位数是第(m+n)/2和第(m+n)/2+1个数的平均值。
  • 使用二分查找来寻找第k小的数。
  • 每次比较两个数组的第k/个数,排除掉不可能的部分。

具体步骤:

  • 确定中位数的位置k。
  • 在两个数组中进行二分查找:
  1. 比较两个数组中第k/2个数的大小。
  2. 较小的那部分不可能是包含第k小的数。
  3. 排除较小的部分,继续查找剩余部分。
  • 递归进行上述过程,直到找到目标数。

时间复杂度:O(log(m+n))

空间复杂度:O(1)

public class Solution
{
    public double FindMedianSortedArrays(int[] nums1,int[] nums2)
{
    int totalLength = nums1.length+nums2.length;
    if(totalLength % 2 ==1)//奇数
    {
        return FindKth(nums1,0,nums2,0,totalLength/2+1);
    }else{  //偶数个元素,注意是除以2.0,保证最后结果除完全
        return  
     (FindKth(nums1,0,nums2,0,totalLength/2)+FindKth(nums1,0,nums2,0,totalLength/2+1))/2.0;
    }
}
}

private double FindKth(int[] nums1,int start1,int[] nums2,int start2,int k)
{
    //如果数组1已经用完,直接从数组2中返回第k个数
    if(start1>=nums1.length)  return nums2[start2+k-1];
    //如果数组2已经用完,直接从数组1中返回第k个数
    if(start2>=nums2.length)   return num1[start1+k-1];
    //如果k==1,返回两个数组开头较小的数
    if(k==1)   return Math.Min(nums1[start1],nums2[start2]);
    //比较两个数组中第k/2个数的大小
    int mid1 = start1+k/2-1<nums1.length ? nums1[start1+k/2-1] : int.MaxValue;
    int mid2 = start2+k/2-1<nums2.length ? nums2[start2+k/2-1] : int.MaxValue;
    
    if(mid1<mid2)  return FindKth(nums1,start1+k/2,nums2,start2,k-k/2);
    else  return FindKth(nums1,start1,nums2,start2+k/2,k-k/2);
}

方法二:合并数组法 ---- 不会超时(好理解一些)

将两个正序的数组合并到一个正序数组当中,最后根据整体数组的奇偶性,直接输出中位数。

//定义一个函数findMedianSortedArrays,它接收四个参数,两个数组nums1和nums2,以及它们的长度//nums1Size和num2Size.
double findMedianSortedArrays(int* nums1,int nums1Size,int* nums2,int nums2Size)
{
    //定义p1和p2指针,初始位置为数组的开始位置
    int p1=0,p2=0,m=0,l=0,k=0,q,n;//m用于存储合并后的数组的长度
                        //q用于存储从nums1和nums2中取出的元素,n用于存储中位数
    int arr[nums1Size + nums2Size]; //arr数组用于存储合并后的数组
    while(p1<nums1Size || p2<nums2Size)
    {
        if(p1==nums1Size)  q=nums2[p2++];       //遍历完nums1       
        else if(p2==nums2Size)  q=nums1[p1++];        //遍历完nums2
        else if(nums1[p1]<nums2[p2])   q=nums1[p1++];  //先从小的开始加入arr数组
        else    q=nums2[p2++];
        arr[p1+p2-1] =q;//将q放入arr数组当中,注意-1是根据数组索引

    }
    m=sizeof(arr)/sizeof(int);  //or m=nums1Size+nums2Size;
    if(m==1) return arr[m-1]; //只有一个元素的数组
    else{
            if(m%2==0)  n=(arr[m/2]+arr[m/2-1])/2.0;//偶数个元素
            else    n=arr[m/2];  //奇数个元素
        }
    return n;
}

相关文章:

  • Linux的chmod命令,给文件设置权限
  • 【Agent实战】货物上架位置推荐助手(RAG方式+结构化prompt(CoT)+API工具结合ChatGPT4o能力Agent项目实践)
  • STC89C52单片机学习——第17节: [7-1]定时器
  • vue中常见面试题(会不断更新版)
  • 深度解读DeepSeek部署使用安全(48页PPT)(文末有下载方式)
  • 鸿蒙移动应用开发--UI组件及应用
  • Unity打包Android平台调用sherpa-onnx
  • 【VUE2】第五期——VueCli创建项目、Vuex多组件共享数据、json-server——模拟服务端api
  • MySQL隐式依赖引发的字段长度溢出:一次触发器事故的深度剖析
  • RK3588 openssl-3.4.1 编译安装
  • esProc SPL vs DuckDB:多源数据处理谁更胜一筹?
  • 编程自学指南:java程序设计开发,反射与注解,反射机制,注解
  • 【商城实战(31)】从0到1:商城项目部署全攻略
  • 提升模型准确性的关键技术与实践指南
  • Qt5中视口(ViewPort)与窗口(Window)
  • WordPress顶部菜单自定义的方法
  • Android studio运行报错处理
  • 反射、反射调用以及修改成员变量,成员方法,构造函数、反射的应用
  • Ubuntu22.04 安装 Isaac gym 中出现的问题
  • jEasyUI 基本的拖动和放置
  • 中美大幅下调超100%关税,印巴四日“战争”复盘|907编辑部
  • 人民币对美元即期汇率盘中创半年新高,离岸市场升破7.2
  • 区域国别学视域下的东亚文化交涉
  • 文学花边|对话《借命而生》原著作者石一枫:我给剧打90分
  • 5月12日-14日,上海小升初民办初中进行网上报名
  • 家电维修担心遇“李鬼”?上海推动“物业+专业服务”进社区