寻找两个正序数组的中位数:分治法与二分查找的结合

寻找两个正序数组的中位数:分治法与二分查找的结合

在算法领域,“寻找两个正序数组的中位数” 是一道经典的高频面试题(LeetCode 第 4 题)。它不仅考察基本的数组操作,还涉及二分查找分治思想的结合。今天,我们就来深入剖析这道题,并用详细代码讲解其高效解法。

1. 题目分析

给定两个大小分别为 mn有序数组 nums1nums2,要求找出它们合并后的中位数。要求算法的时间复杂度为 O(log(m + n))

1.1 示例

输入

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

输出

2.0

输入

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

输出

2.5

2. 朴素解法:归并再求中位数(O(m + n))

最直观的方法是将两个有序数组合并,然后直接找到中位数。但由于合并过程需要 O(m + n) 时间,不满足 O(log(m + n)) 的要求,所以我们需要更优的方法。

3. 高效解法:二分查找 + 分治思想

我们可以利用二分查找来优化,核心思路如下:

  • nums1nums2 的总长度为 m + n
  • 我们的目标是找到第 (m+n)/2 小的数,而不是直接合并数组。
  • 通过二分查找,在 nums1nums2 之间动态调整搜索范围,逐步逼近答案。

4. 代码实现(Python)

def findMedianSortedArrays(nums1, nums2):# 确保 nums1 的长度不大于 nums2if len(nums1) > len(nums2):nums1, nums2 = nums2, nums1m, n = len(nums1), len(nums2)left, right = 0, mmedian_pos = (m + n + 1) // 2  # 找到中位数的位置while left <= right:partition1 = (left + right) // 2  # 切割 nums1partition2 = median_pos - partition1  # 确保左半部分的总元素个数# 获取切割后的左右元素maxLeft1 = float('-inf') if partition1 == 0 else nums1[partition1 - 1]minRight1 = float('inf') if partition1 == m else nums1[partition1]maxLeft2 = float('-inf') if partition2 == 0 else nums2[partition2 - 1]minRight2 = float('inf') if partition2 == n else nums2[partition2]# 检查是否找到合适的划分if maxLeft1 <= minRight2 and maxLeft2 <= minRight1:# 如果元素总数是奇数,返回左侧最大值if (m + n) % 2 == 1:return max(maxLeft1, maxLeft2)# 否则返回两个中间值的均值return (max(maxLeft1, maxLeft2) + min(minRight1, minRight2)) / 2# 调整二分查找范围elif maxLeft1 > minRight2:right = partition1 - 1  # 左移else:left = partition1 + 1  # 右移

5. 代码解析

核心思想

  • 通过二分查找,我们试图在 nums1nums2 中找到一个合适的切割,使得两部分满足条件:
    • 左半部分的最大值 ≤ 右半部分的最小值
  • 我们使用 partition1partition2 来划分 nums1nums2
  • 通过调整 partition1 的位置,动态缩小范围,最终找到中位数。

时间复杂度

  • 由于每次搜索都将 nums1 的搜索范围缩小一半,因此时间复杂度为 O(log(min(m, n)))

6. 为什么用二分查找?

这道题的核心是不合并数组,直接找到中位数

  • 由于数组是有序的,我们可以利用二分查找,只关注中位数的位置,而不是整个数组。
  • 通过不断调整 partition1 的位置,我们可以快速确定划分点,而不需要合并数组。

7. 总结

在这篇文章中,我们学习了寻找两个正序数组的中位数的最优解法:

  • 朴素解法:合并后找中位数(O(m + n))。
  • 二分查找 + 分治法:不合并数组,直接在 nums1nums2 之间找到合适的划分点(O(log(min(m, n))))。

这道题不仅考察二分查找的应用,还涉及分治思想,是典型的高效算法设计题目。希望这篇文章能帮助你理解这道经典算法题,也欢迎交流更优解法!

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

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

相关文章

STM32 PWM驱动舵机

接线图&#xff1a; 这里将信号线连接到了开发板的PA1上 代码配置&#xff1a; 这里的PWM配置与呼吸灯一样&#xff0c;呼吸灯连接的是PA0引脚&#xff0c;输出比较单元用的是OC1通道&#xff0c;这里只需改为OC2通道即可。 完整代码&#xff1a; #include "servo.h&quo…

使用 concurrently 实现前后端一键启动

使用 concurrently 实现前后端一键启动 本文适合&#xff1a; 前后端分离项目&#xff08;如 React Node.js&#xff09;&#xff0c;希望通过一条命令同时启动前端和后端服务。 工具链&#xff1a; Node.js、npm、concurrently。 耗时&#xff1a; 3 分钟。 文章目录 使用 c…

【NLP251】NLP RNN 系列网络

NLP251 系列主要记录从NLP基础网络结构到知识图谱的学习 &#xff11;.原理及网络结构 &#xff11;.&#xff11;&#xff32;&#xff2e;&#xff2e; 在Yoshua Bengio论文中( http://proceedings.mlr.press/v28/pascanu13.pdf )证明了梯度求导的一部分环节是一个指数模型…

OpenCV:在图像中添加噪声(瑞利、伽马、脉冲、泊松)

目录 简述 1. 瑞利噪声 2. 伽马噪声 3. 脉冲噪声 4. 泊松噪声 总结 相关阅读 OpenCV&#xff1a;在图像中添加高斯噪声、胡椒噪声-CSDN博客 OpenCV&#xff1a;高通滤波之索贝尔、沙尔和拉普拉斯-CSDN博客 OpenCV&#xff1a;图像处理中的低通滤波-CSDN博客 OpenCV&…

小智 AI 聊天机器人

小智 AI 聊天机器人 &#xff08;XiaoZhi AI Chatbot&#xff09; &#x1f449;参考源项目复现 &#x1f449; ESP32SenseVoiceQwen72B打造你的AI聊天伴侣&#xff01;【bilibili】 &#x1f449; 手工打造你的 AI 女友&#xff0c;新手入门教程【bilibili】 项目目的 本…

亚博microros小车-原生ubuntu支持系列:16 机器人状态估计

本来想测试下gmapping建图&#xff0c;但是底层依赖了yahboomcar_bringup做底层的数据处理&#xff0c;所以先把依赖的工程导入。 程序启动后&#xff0c;会订阅imu和odom数据&#xff0c;过滤掉一部分的imu数据后&#xff0c;然后与odom数据进行融合&#xff0c;最后输出一个…

C++中的类与对象(中)

在上一节中&#xff0c;我们初步了解了一下&#xff0c;C中的类&#xff0c;这一概念&#xff0c;这一节让我们进一步深入了解一下。 文章目录 目录 前言 一、类中的默认成员函数 1.1 构造函数 构造函数的特点&#xff1a; 1.2 析构函数 析构函数的特点&#xff1a; 1.3 …

Kotlin开发(六):Kotlin 数据类,密封类与枚举类

引言 想象一下&#xff0c;你是个 Kotlin 开发者&#xff0c;敲着代码忽然发现业务代码中需要一堆冗长的 POJO 类来传递数据。烦得很&#xff1f;别急&#xff0c;Kotlin 贴心的 数据类 能帮你自动生成 equals、hashCode&#xff0c;直接省时省力&#xff01;再想想需要多种状…

redis数据安全与性能保障

数据安全与性能保障 1、持久化1.1 快照持久化1.2 AOF持久化1.3 重写/压缩AOF文件 2、复制2.1 Redis复制的启动过程2.2 主从链 3、处理系统故障3.1 验证快照文件和AOF文件 4、事务4.1 java中的redis事务使用 如有侵权&#xff0c;请联系&#xff5e; 如有错误&#xff0c;也欢迎…

数据分析系列--③RapidMiner算子说明及数据预处理

一、算子说明 1.新建过程 2.算子状态灯 状态灯说明: (1)状态指示灯&#xff1a; 红色:指示灯说明有参数未被设置或输入端口未被连接等问题; 黄色:指示灯说明还未执行算子&#xff0c;不管配置是否基本齐全; 绿色:指示灯说明一切正常&#xff0c;已成功执行算子。 (2)三角…

基于Go语言的三甲医院人机与智能体协同环境系统(上.文章部分)

一、引言 1.1 研究背景与意义 1.1.1 三甲医院对高效协同系统的需求 三甲医院作为医疗体系的核心力量,承担着疑难病症诊治、医学科研教学等重要任务,其业务具有高度的复杂性。在日常运营中,三甲医院涉及多个科室,每个科室又包含众多专业领域,各科室之间需要紧密协作,共…

js笔记(黑马程序员)

&#xff08;Web APIs day4&#xff09; 一、日期对象 1.实例化 在代码中发现了 new 关键字时&#xff0c;一般将这个操作称为实例化 创建一个时间对象并获取时间// 1&#xff0e;得到当前时间 2.日期对象方法 因为日期对象返回的数据我们不能直接使用&#xff0c;所以需…

SOME/IP--协议英文原文讲解2

前言 SOME/IP协议越来越多的用于汽车电子行业中&#xff0c;关于协议详细完全的中文资料却没有&#xff0c;所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块&#xff1a; 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 4.1 Speci…

python-leetcode-反转链表 II

92. 反转链表 II - 力扣&#xff08;LeetCode&#xff09; # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val val # self.next next class Solution:def reverseBetween(self, head: Optional…

LM Studio 本地部署DeepSeek及其他AI模型的详细操作教程及硬件要求

本篇文章主要讲解&#xff0c;通过LM Studio工具实现各类型AI模型本地部署的操作方法方式。 作者&#xff1a;任聪聪 日期&#xff1a;2025年1月29日 LM Studio 介绍&#xff1a; LM Studio是一款能够本地离线运行各类型大语言模型的客户端应用&#xff0c;通过LM Studio 可以…

SOME/IP--协议英文原文讲解3

前言 SOME/IP协议越来越多的用于汽车电子行业中&#xff0c;关于协议详细完全的中文资料却没有&#xff0c;所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块&#xff1a; 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 Note: Thi…

Janus Pro:DeepSeek 开源革新,多模态 AI 的未来

Janus Pro 是 DeepSeek 开发的一个开源多模态人工智能框架&#xff0c;它通过集成视觉和语言处理能力&#xff0c;提供了高性能的多模态任务处理能力。 在线体验&#xff1a; https://deepseek-januspro.com/ 背景 Janus Pro 于2025年1月发布&#xff0c;是一个开源的多模态…

Jenkins上生成的allure report打不开怎么处理

目录 问题背景&#xff1a; 原因&#xff1a; 解决方案&#xff1a; Jenkins上修改配置 通过Groovy脚本在Script Console中设置和修改系统属性 步骤 验证是否清空成功 进一步的定制 也可以使用Nginx去解决 使用逆向代理服务器Nginx&#xff1a; 通过合理调整CSP配置&a…

指针的介绍3前

1.字符指针变量 1.1介绍 char arr[] "abcdef";char* p arr; 上面的代码中&#xff0c;我创建了 字符数组 arr 来存储一个字符串 此时&#xff0c;我可以创建一个指针变量对这个字符串进行相应的修改&#xff1a; 我也可以创建一个指针变量指向一个字符串&#xff…

Scrapy如何设置iP,并实现IP重用, IP代理池重用

前置知识 1/3乐观锁 2/3 Scrapy流程(非全部) 3/3 关于付费代理 我用的"快代理", 1000个ip, 每个ip1min的有效期, 你用的时候, 把你的链接, 用户名填上去就行 设置代理IP &#x1f512; & 帮助文档: ①meta ②meta#proxy$ 语法: ①proxy的设置: Request对象中…