给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。

示例 1:

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

示例 2:

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

给定两个有序数组,要求找到两个有序数组的中位数,最直观的思路有以下两种:

使用归并的方式,合并两个有序数组,得到一个大的有序数组。大的有序数组的中间位置的元素,即为中位数。

不需要合并两个有序数组,只要找到中位数的位置即可。由于两个数组的长度已知,因此中位数对应的两个数组的下标之和也是已知的。维护两个指针,初始时分别指向两个数组的下标 0 的位置,每次将指向较小值的指针后移一位(如果一个指针已经到达数组末尾,则只需要移动另一个数组的指针),直到到达中位数的位置。

假设两个有序数组的长度分别为 m 和 n,上述两种思路的复杂度如何?

第一种思路的时间复杂度是 O(m+n),空间复杂度是 O(m+n)。第二种思路虽然可以将空间复杂度降到 O(1),但是时间复杂度仍是 O(m+n)。

如何把时间复杂度降低到 O(log(m+n)) 呢?如果对时间复杂度的要求有 log,通常都需要用到二分查找,这道题也可以通过二分查找实现。

根据中位数的定义,当 m+n 是奇数时,中位数是两个有序数组中的第 (m+n)/2 个元素,当 m+n 是偶数时,中位数是两个有序数组中的第 (m+n)/2 个元素和第 (m+n)/2+1 个元素的平均值。因此,这道题可以转化成寻找两个有序数组中的第 k 小的数,其中 k 为 (m+n)/2 或 (m+n)/2+1。

假设两个有序数组分别是 A 和 B。要找到第 k 个元素,我们可以比较 A[k/2−1] 和 B[k/2−1],其中 / 表示整数除法。由于 A[k/2−1] 和 B[k/2−1] 的前面分别有 A[0..k/2−2] 和 B[0..k/2−2],即 k/2−1 个元素,对于 A[k/2−1] 和 B[k/2−1] 中的较小值,最多只会有 (k/2−1)+(k/2−1)≤k−2 个元素比它小,那么它就不能是第 k 小的数了。

因此我们可以归纳出三种情况:

如果 A[k/2−1]<B[k/2−1],则比 A[k/2−1] 小的数最多只有 A 的前 k/2−1 个数和 B 的前 k/2−1 个数,即比 A[k/2−1] 小的数最多只有 k−2 个,因此 A[k/2−1] 不可能是第 k 个数,A[0] 到 A[k/2−1] 也都不可能是第 k 个数,可以全部排除。

如果 A[k/2−1]>B[k/2−1],则可以排除 B[0] 到 B[k/2−1]。

如果 A[k/2−1]=B[k/2−1],则可以归入第一种情况处理。

可以看到,比较 A[k/2−1] 和 B[k/2−1] 之后,可以排除 k/2 个不可能是第 k 小的数,查找范围缩小了一半。同时,我们将在排除后的新数组上继续进行二分查找,并且根据我们排除数的个数,减少 k 的值,这是因为我们排除的数都不大于第 k 小的数。

有以下三种情况需要特殊处理:

如果 A[k/2−1] 或者 B[k/2−1] 越界,那么我们可以选取对应数组中的最后一个元素。在这种情况下,我们必须根据排除数的个数减少 k 的值,而不能直接将 k 减去 k/2。

如果一个数组为空,说明该数组中的所有元素都被排除,我们可以直接返回另一个数组中第 k 小的元素。

如果 k=1,我们只要返回两个数组首元素的最小值即可。

用一个例子说明上述算法。假设两个有序数组如下:

A: 1 3 4 9
B: 1 2 3 4 5 6 7 8 9
两个有序数组的长度分别是 4 和 9,长度之和是 13,中位数是两个有序数组中的第 7 个元素,因此需要找到第 k=7 个元素。

比较两个有序数组中下标为 k/2−1=2 的数,即 A[2] 和 B[2],如下面所示:

A: 1 3 4 9

B: 1 2 3 4 5 6 7 8 9

由于 A[2]>B[2],因此排除 B[0] 到 B[2],即数组 B 的下标偏移(offset)变为 3,同时更新 k 的值:k=k−k/2=4。

下一步寻找,比较两个有序数组中下标为 k/2−1=1 的数,即 A[1] 和 B[4],如下面所示,其中方括号部分表示已经被排除的数。

A: 1 3 4 9

B: [1 2 3] 4 5 6 7 8 9

由于 A[1]<B[4],因此排除 A[0] 到 A[1],即数组 A 的下标偏移变为 2,同时更新 k 的值:k=k−k/2=2。

下一步寻找,比较两个有序数组中下标为 k/2−1=0 的数,即比较 A[2] 和 B[3],如下面所示,其中方括号部分表示已经被排除的数。

A: [1 3] 4 9

B: [1 2 3] 4 5 6 7 8 9

由于 A[2]=B[3],根据之前的规则,排除 A 中的元素,因此排除 A[2],即数组 A 的下标偏移变为 3,同时更新 k 的值: k=k−k/2=1。

由于 k 的值变成 1,因此比较两个有序数组中的未排除下标范围内的第一个数,其中较小的数即为第 k 个数,由于 A[3]>B[3],因此第 k 个数是 B[3]=4。

A: [1 3 4] 9

B: [1 2 3] 4 5 6 7 8 9

class Solution {
public:double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {if (nums1.size() > nums2.size()) {return findMedianSortedArrays(nums2, nums1);}int m = nums1.size();int n = nums2.size();int left = 0, right = m;// median1:前一部分的最大值// median2:后一部分的最小值int median1 = 0, median2 = 0;while (left <= right) {// 前一部分包含 nums1[0 .. i-1] 和 nums2[0 .. j-1]// 后一部分包含 nums1[i .. m-1] 和 nums2[j .. n-1]int i = (left + right) / 2;int j = (m + n + 1) / 2 - i;// nums_im1, nums_i, nums_jm1, nums_j 分别表示 nums1[i-1], nums1[i], nums2[j-1], nums2[j]int nums_im1 = (i == 0 ? INT_MIN : nums1[i - 1]);int nums_i = (i == m ? INT_MAX : nums1[i]);int nums_jm1 = (j == 0 ? INT_MIN : nums2[j - 1]);int nums_j = (j == n ? INT_MAX : nums2[j]);if (nums_im1 <= nums_j) {median1 = max(nums_im1, nums_jm1);median2 = min(nums_i, nums_j);left = i + 1;} else {right = i - 1;}}return (m + n) % 2 == 0 ? (median1 + median2) / 2.0 : median1;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/917071.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/917071.shtml
英文地址,请注明出处:http://en.pswp.cn/news/917071.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

监控场景视频质量异常修复:陌讯动态增强算法实战解析

原创声明&#xff1a;本文为原创技术解析&#xff0c;核心技术参数与架构引用自《陌讯技术白皮书》&#xff0c;禁止未经授权转载。一、行业痛点&#xff1a;视频质量异常的连锁难题在安防监控、智慧交通等场景中&#xff0c;视频质量异常已成为 AI 分析的主要瓶颈。据行业报告…

一个简单的mvvm示例与数据双向绑定

这就是一个简单的数据双向绑定的demo&#xff0c;参考即可&#xff08;cmakelist我没按他的写&#xff0c;但是大差不差&#xff09; 目录 1.示例demo File: CMakeLists.txt File: main.cpp File: model/physiologymodel.cpp File: viewmodel/physiologyviewmodel.h Fil…

哈希的概念及其应用

哈希的概念及其应用哈希概念常见的哈希其他哈希字符串哈希&#xff08;算法竞赛常用&#xff09;字符串哈希OJP3370 【模板】字符串哈希 - 洛谷P10468 兔子与兔子 - 洛谷哈希冲突哈希函数设计原则哈希冲突解决方法—闭散列闭散列的线性探测闭散列的二次探测哈希冲突解决方法—开…

【分布式的个人博客部署】

综合项目-搭建个人博客一、运行环境二、基础配置三、业务需求第一步&#xff1a;准备工作1、配置静态IP2、修改hosts映射3、开启防火墙4、时间同步5、配置免密ssh登录第二步&#xff1a;环境搭建1、Server-web端安装LNMP环境软件2、Server-NFS-DNS端上传博客软件3、Server-NFS-…

蓝桥杯----DS18B20温度传感器

&#xff08;二&#xff09;、温度传感器1、One-Wire总线One-Wire总线利用一根线实现双向通信。因此其协议对时序的要求较严格&#xff0c;如应答等时序都有明确的时间要求。基本的时序包括复位及应答时序、写一位时序读一位时序。单总线即只有一根数据线&#xff0c;系统中的数…

科技赋能成长 脑力启迪未来

——西安臻昊科技与秦岭云数智共筑脑科学教育新生态 2025年6月26日&#xff0c;西安臻昊科技&#xff08;集团&#xff09;有限责任公司与秦岭云数智&#xff08;陕西&#xff09;科技有限公司正式签署脑象评测技术战略合作协议&#xff0c;双方将依托技术互补与资源协同&#…

Docker部署的PostgreSQL慢查询日志配置指南

目录 1. 核心步骤 1.1 修改配置文件 1.2 动态加载配置&#xff08;无需重启容器&#xff09; 1.3 验证配置生效 1.3.1 查看参数 1.3.2 执行测试慢查询 2. 高级用法 2.1 使用分析工具 2.2 启用扩展 3. 注意事项 3.1 日志目录权限 3.2 性能影响 配置Docker部署的Pos…

C# 入门教程(四)委托详解

文章目录1、什么是委托2、委托的声明&#xff08;自定义委托&#xff09;3、委托的使用3.1 实例:把方法当作参数传给另一个方法3.2 注意:难精通易使用功能强大东西&#xff0c;一旦被滥用则后果非常严重4、委托的高级使用4.1 多播&#xff08;multicast&#xff09;委托4.2隐式…

React的基本语法和原理

3. React条件渲染某些情况下&#xff0c;姐妹的内容会根据不同的情况显示不同的内容&#xff0c;或者决定是否渲染某部分内容&#xff1a; 在React中&#xff0c;所有的条件判断和普通的JavaScript代码一致&#xff1b;常见的条件渲染的方式有哪些&#xff1f;方式一&#xff1…

如何在 Gradle 项目中添加依赖?(以添加 AndroidX 版本的 RecyclerView 为例)

1. 确保项目已启用 AndroidX RecyclerView 的现代版本属于 AndroidX 库&#xff0c;需确保项目已启用 AndroidX&#xff1a; 在 gradle.properties 中应有以下配置&#xff08;通常新建项目默认开启&#xff09;&#xff1a;android.useAndroidXtrue android.enableJetifiert…

深度学习与图像处理 | 基于PaddlePaddle的梯度下降算法实现(线性回归投资预测)

演示基于PaddlePaddle自动求导技术实现梯度下降&#xff0c;简化求解过程。01、梯度下降法梯度下降法是机器学习领域非常重要和具有代表性的算法&#xff0c;它通过迭代计算来逐步寻找目标函数极小值。既然是一种迭代计算方法&#xff0c;那么最重要的就是往哪个方向迭代&#…

负载均衡集群HAproxy

HAProxy 简介HAProxy 是一款高性能的负载均衡器和代理服务器&#xff0c;支持 TCP 和 HTTP 应用。广泛用于高可用性集群&#xff0c;能够有效分发流量到多个后端服务器&#xff0c;确保服务的稳定性和可扩展性。HAProxy 核心功能负载均衡&#xff1a;支持轮询&#xff08;round…

重生之我在10天内卷赢C++ - DAY 1

坐稳了&#xff0c;我们的C重生之旅现在正式发车&#xff01;请系好安全带&#xff0c;前方高能&#xff0c;但绝对有趣&#xff01;&#x1f680; 重生之我在10天内卷赢C - DAY 1导师寄语&#xff1a;嘿&#xff0c;未来的编程大神&#xff01;欢迎来到C的世界。我知道&#x…

[mind-elixir]Mind-Elixir 的交互增强:单击、双击与鼠标 Hover 功能实现

[mind-elixir]Mind-Elixir 的交互增强&#xff1a;单击、双击与鼠标 Hover 功能实现 功能简述 通过防抖&#xff0c;实现单击双击区分通过mousemove事件&#xff0c;实现hover效果 实现思路 &#xff08;一&#xff09;单击与双击事件 功能描述 单击节点时&#xff0c;可以触发…

c++-迭代器类别仿函数常用算法函数

C常用算法函数 1. 前置知识 1.1 迭代器的类别 C中&#xff0c;迭代器是 STL 容器库的核心组件之一&#xff0c;具有举足轻重的作用&#xff0c;它提供了一种 统一的方式来访问和遍历容器&#xff0c;而无需关心底层数据结构的具体实现。迭代器类似指针&#xff0c;但比指针更通…

Python深度学习框架TensorFlow与Keras的实践探索

基础概念与安装配置 TensorFlow核心架构解析 TensorFlow是由Google Brain团队开发的开源深度学习框架&#xff0c;其核心架构包含数据流图&#xff08;Data Flow Graph&#xff09;和张量计算系统。数据流图通过节点表示运算操作&#xff08;如卷积、激活函数&#xff09;&…

c# net6.0+ 安装中文智能提示

https://github.com/stratosblue/IntelliSenseLocalizer 1、安装tool dotnet tool install -g islocalizer 2、 安装IntelliSense 文件&#xff0c;安装其他net版本修改下版本号 安装中文net6.0采集包 islocalizer install auto -m net6.0 -l zh-cn 安装中英文双语net6.0采集包…

【建模与仿真】二阶邻居节点信息驱动的节点重要性排序算法

导读&#xff1a; 在复杂网络中&#xff0c;挖掘重要节点对精准推荐、交通管控、谣言控制和疾病遏制等应用至关重要。为此&#xff0c;本文提出一种局部信息驱动的节点重要性排序算法Leaky Noisy Integrate-and-Fire (LNIF)。该算法通过获取节点的二阶邻居信息计算节点重要性&…

指令微调Qwen3实现文本分类任务

参考文档&#xff1a; SwanLab入门深度学习&#xff1a;Qwen3大模型指令微调 - 肖祥 - 博客园 vLLM&#xff1a;让大语言模型推理更高效的新一代引擎 —— 原理详解一_vllm 原理-CSDN博客 概述 为了实现对100个标签的多标签文本分类任务&#xff0c;前期调用gpt-4o进行prom…

【机器学习-3】 | 决策树与鸢尾花分类实践篇

0 序言 本文将深入探讨决策树算法&#xff0c;先回顾下前边的知识&#xff0c;从其基本概念、构建过程讲起&#xff0c;带你理解信息熵、信息增益等核心要点。 接着在引入新知识点&#xff0c;介绍Scikit - learn 库中决策树的实现与应用&#xff0c;再通过一个具体项目的方式来…