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

server/2024/11/28 3:25:06/

力扣 4. 寻找两个正序数组的中位数 

思路:

  1. 二分查找标记位
  2. 计算中位数

细节:

if (nums1.size() > nums2.size())return findMedianSortedArrays(nums2, nums1);

首先比较两个数组的大小,确保后续 nums1 的长度总是小于等于 nums2 的长度

int m = nums1.size();
int n = nums2.size();
int l = 0, r = m, halfLen = (m + n + 1) / 2;

计算出合并后数组左半部分的长度 halfLen+1可确保合并后总长度为奇数时halfLen为中位数

while (l <= r) 
{int mid1 = (l + r) / 2;int mid2 = halfLen - mid1;if (mid1 < r && nums1[mid1] < nums2[mid2 - 1])l = mid1 + 1;else if (mid1 > l && nums1[mid1 - 1] > nums2[mid2])r = mid1 - 1;else{// 后续处理中位数}
}

通过二分法不断调整 mid1( nums1 的标记位)来找到合适的划分点,并在每次循环中,根据当前的 mid1 计算出对应的 mid2( nums2 的标记位)保证 mid1 + mid2 = halfLen

mid1和mid2的 )左边 即左半部分
mid1和mid2的 右边( 即右半部分 

  • 当 mid1 < r 且 nums1[mid1] < nums2[mid2 - 1] 时,意味着当前 nums1 中划分位置 mid1 处的值太小了,导致 nums1 左半部分的最大值小于 nums2 右半部分的最小值,所以需要将 l(左边界)向右移动,即增大 mid1 的值,尝试新的划分。
  • 当 mid1 > l 且 nums1[mid1 - 1] > nums2[mid2] 时,说明当前 nums1 中划分位置 mid1 处的值太大了,导致 nums1 右半部分的最小值小于 nums2 左半部分的最大值,所以需要将 r(右边界)向左移动,即减小 mid1 的值,再尝试新的划分。

当上述两个调整边界的条件都不满足时,说明找到了合适的划分点,进入后续计算中位数的逻辑。


int maxL = 0;
if (mid1 == 0) maxL = nums2[mid2 - 1];
else if (mid2 == 0) maxL = nums1[mid1 - 1];
elsemaxL = max(nums1[mid1 - 1], nums2[mid2 - 1]);if ((m + n) % 2 == 1)return maxL;
  • 左半部分最大值计算
    • 初始化 maxL 存储合并后数组左半部分的最大值。
    • 如果 mid1 为 0,说明 nums1 的左半部分没有元素,那么当前左半部分最大值就是 nums2 中对应划分位置 mid2 - 1 处的元素。
    • 如果 mid2 为 0,说明 nums2 的左半部分没有元素,那么当前左半部分最大值就是 nums1 中对应划分位置 mid1 - 1 处的元素。
    • 否则,取 nums1[mid1 - 1] 和 nums2[mid2 - 1] 中的较大值作为左半部分的最大值,这是因为合并后有序数组左半部分的最大值必然是这两个值中的较大者
  • 根据总长度奇偶性处理返回值
    • 如果 (m + n) % 2 == 1,即合并后的数组长度为奇数,此时中位数就是左半部分的最大值 maxL,直接返回该值即可。
int minR = 0;
if (mid1 == m)minR = nums2[mid2];
else if (mid2 == n)minR = nums1[mid1];
elseminR = min(nums1[mid1], nums2[mid2]);return (maxL + minR) / 2.0;
  • 右半部分最小值计算(数组长度为偶数时需要)
    • 初始化 minR 存储合并后数组右半部分的最小值。
    • 如果 mid1 等于 m,意味着 nums1 的右半部分没有元素,那么右半部分最小值就是 nums2 中对应划分位置 mid2 处的元素。
    • 如果 mid2 等于 n,意味着 nums2 的右半部分没有元素,那么右半部分最小值就是 nums1 中对应划分位置 mid1 处的元素。
    • 否则,取 nums1[mid1] 和 nums2[mid2] 中的较小值作为右半部分的最小值,这因为合并后有序数组右半部分的最小值必然是这两个值中的较小者
  • 最终返回中位数(数组长度为偶数时)
    • 当合并后的数组长度为偶数时,中位数是左半部分最大值 maxL 和右半部分最小值 minR 的平均值,所以返回 (maxL + minR) / 2.0

例如:

 

总代码:

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 l = 0, r = m, halfLen = (m + n + 1) / 2;while (l <= r) {int mid1 = (l + r) / 2;//nums1的midint mid2 = halfLen - mid1;//nums2的midif (mid1 < r && nums1[mid1] < nums2[mid2 - 1])l = mid1 + 1;//nums1[mid1]小于nums2[mid2 - 1],说明mid1的值偏小了,需要将l向右移动else if (mid1 > l && nums1[mid1 - 1] > nums2[mid2])r = mid1 - 1;//nums1[mid1 - 1]大于nums2[mid2],说明mid1的值偏大了,需要将r向左移动else{//处理左半部分最大值int maxL = 0;if (mid1 == 0) //当mid1为 0 时,左半部分最大值就是nums2[mid2 - 1]maxL = nums2[mid2 - 1];else if (mid2 == 0) //当mid2为 0 时,左半部分最大值就是nums1[mid1 - 1]maxL = nums1[mid1 - 1];elsemaxL = max(nums1[mid1 - 1], nums2[mid2 - 1]);//取nums1[mid1 - 1]和nums2[mid2 - 1]中的较大值if ((m + n) % 2 == 1)//奇数则直接取左半部分最大值return maxL;//处理右半部分最小值int minR = 0;if (mid1 == m)//当mid1为 m 时,右半部分最小值就是nums2[mid2]minR = nums2[mid2];else if (mid2 == n)//当mid2为 n 时,右半部分最小值就是nums1[mid1]minR = nums1[mid1];elseminR = min(nums1[mid1], nums2[mid2]);//取nums1[mid1]和nums2[mid2]中的较小值return (maxL + minR) / 2.0;}}return 0;}
};

 


http://www.ppmy.cn/server/145512.html

相关文章

基于机器学习的人脸识别算法matlab仿真,对比GRNN,PNN,DNN以及BP四种网络

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 MATLAB2022A 3.部分核心程序 &#xff08;完整版代码包含详细中文注释和操作步骤视频&#xff09…

上天入地 灵途科技光电技术赋能空间感知

近来&#xff0c;人工智能技术频频亮相各大马拉松赛事&#xff0c;成为引人注目的科技亮点。 11月3日&#xff0c;杭州马拉松首次启用了机器狗作为配速员&#xff0c;以稳定的节奏为选手提供科学的跑步节奏。 11月11日&#xff0c;亦庄半程马拉松的终点处&#xff0c;人形机器…

AWTK-WIDGET-WEB-VIEW 实现笔记 (2) - Windows

在 Windows 平台上的实现&#xff0c;相对比较顺利&#xff0c;将一个窗口嵌入到另外一个窗口是比较容易的事情。 1. 创建窗口 这里有点需要注意&#xff1a; 父窗口的大小变化时&#xff0c;子窗口也要跟着变化&#xff0c;否则 webview 显示不出来。创建时窗口的大小先设置…

VTK编程指南<二>:VTK9.3.1+VS2019+Qt5.15.2编译及环境配置

VTK&#xff08;Visualization Toolkit&#xff09;是一个开源的、跨平台的三维可视化开发库&#xff0c;用于处理和可视化三维数据。它提供了一系列算法和工具&#xff0c;用于创建、操作和渲染复杂的三维图形&#xff0c;并支持多种数据表示方式&#xff0c;包括点、线、面、…

FastChat - 训练和评估大型语言模型的开放平台

更多AI开源软件&#xff1a; AI开源 - 小众AIhttps://www.aiinn.cn/sources 35900 Stars 4400 Forks 739 Issues 253 贡献者 Apache-2.0 License Python 语言 代码: GitHub - lm-sys/FastChat: An open platform for training, serving, and evaluating large language model…

【Python爬虫五十个小案例】爬取猫眼电影Top100

博客主页&#xff1a;小馒头学python 本文专栏: Python爬虫五十个小案例 专栏简介&#xff1a;分享五十个Python爬虫小案例 &#x1f40d;引言 猫眼电影是国内知名的电影票务与资讯平台&#xff0c;其中Top100榜单是影迷和电影产业观察者关注的重点。通过爬取猫眼电影Top10…

【C++知识总结2】C++里面的小配角cout和cin

一、引入 第一个关于输入输出的C代码 #include<iostream> // std是C标准库的命名空间名&#xff0c;C将标准库的定义实现都放到这个命名空间中 using namespace std; int main() {cout<<"Hello world!!!"<<endl;return 0; } 1. 使用cout标准输出…

c++中操作数据库的常用函数

在C中操作数据库&#xff0c;尤其是MySQL数据库&#xff0c;主要通过MySQL提供的C API或MySQL Connector/C库来实现。这些库提供了一系列的函数&#xff0c;使得开发者能够在C应用程序中执行数据库的连接、查询、更新、删除等操作。以下是C中操作MySQL数据库的一些常用函数&…