算法题打卡力扣第4题:寻找两个正序数组的中位数(hard))

题目描述

在这里插入图片描述

提示:

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

解答思路

我的想法是先归并排序再直接返回下标中位数
代码

double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {int i=0,j=0,k=0;int c[nums1Size+nums2Size];while(i<nums1Size&&j<nums2Size){if(nums1[i]<nums2[j])c[k++]=nums1[i++];elsec[k++]=nums2[j++];}while(i<nums1Size)c[k++]=nums1[i++];while(j<nums2Size)c[k++]=nums2[j++];if((nums1Size+nums2Size)%2==1)return c[(nums1Size+nums2Size)/2];elsereturn (c[(nums1Size+nums2Size)/2-1]+c[(nums1Size+nums2Size)/2])/2.0;
}

结果
在这里插入图片描述
复杂度分析
时间复杂度:O(m+n)
空间复杂度:O(n+m)

解法二,二分查找法(最优解)

二分查找的算法模板from算法模板

bool check(int x){ /* ... */}//检查x是否满足某种性质//区间[l,r]被划分成[l,mid] 和 [mid+1,r]时使用;
int bsearch_1(int l,int r)
{while(l<r){int mid = l+r >>1;if(check(mid)) r=mid;else l = mid + 1;}return l;
}
//区间[l,r]被划分成[l,mid-1] 和 [mid,r]时使用:
int bsearch_2(int l,int r)
{while(l<r){int mid = l+r+1>>1;if(check(mid)) l=mid;else r=mid-1;}return l;
}

既然题目要求对数级别的时间复杂度,我们必须考虑使用二分查找。这里的难点在于,我们不是在一个简单的数组上进行二分,而是在一个“虚拟”的合并数组上进行。

核心思想:转化问题
寻找中位数,本质上是在寻找一个“分割点”,这个分割点能将一个集合分成左右两个部分,且左边部分的所有元素都小于等于右边部分的所有元素。

对于这道题,我们要在 nums1 和 nums2 中找到两个分割点,将两个数组都分成左右两部分。这两个分割点需要满足以下两个条件:
长度条件:左半部分所有元素的个数之和 等于 右半部分所有元素的个数之和(或多一个,当总数为奇数时)。
大小条件:左半部分所有元素的最大值 小于等于 右半部分所有元素的最小值。
只要我们找到了满足这两个条件的分割点,中位数就自然而然地由分割点周围的元素决定了

具体步骤:
为了简化,我们假设 nums1 是长度较短的那个数组(如果不是,可以交换它们)。

  • 我们对较短的数组 nums1 进行二分查找。我们要查找的不是一个值,而是一个合适的分割线索引 i。这个 i 将 nums1 分成 nums1[0…i-1](左半部分)和 nums1[i…m-1](右半部分)。

  • 设总长度的一半为 halfLen = (m + n + 1) / 2。(这里 +1 是一个小技巧,可以同时处理奇偶情况)。

  • 一旦 nums1 的分割线 i 确定了,nums2 的分割线 j 也随之确定,必须满足 i + j = halfLen,所以 j = halfLen - i。j 将 nums2 分成 nums2[0…j-1] 和 nums2[j…n-1]。

  • 现在我们有了四个关键的边界值
    nums1 左半部分的最大值:nums1[i-1] (设为 L1)
    nums1 右半部分的最小值:nums1[i] (设为 R1)
    nums2 左半部分的最大值:nums2[j-1] (设为 L2)
    nums2 右半部分的最小值:nums2[j] (设为 R2)

  • 接下来,我们检查“大小条件”是否满足。正确的分割线必须满足:L1 <= R2 并且 L2 <= R1。
    如果 L1 > R2:说明 nums1 的分割线 i 太靠右了,nums1 左边的数太大了。我们需要将 i 向左移动。在二分查找中,这意味着要缩小查找区间的右边界 (high = i - 1)。
    如果 L2 > R1:说明 nums1 的分割线 i 太靠左了,nums1 右边的数太小了(等价于 nums2 左边的数太大了)。我们需要将 i 向右移动。在二分查找中,这意味着要扩大查找区间的左边界 (low = i + 1)。
    如果同时满足 L1 <= R2 和 L2 <= R1:恭喜,我们找到了完美的分割线!现在可以计算中位数了:
    如果总长度 (m+n) 是奇数:中位数就是两个左半部分中的最大值,即 max(L1, L2)。
    如果总长度 (m+n) 是偶数:中位数是左半部分最大值和右半部分最小值的平均值,即 (max(L1, L2) + min(R1, R2)) / 2.0。

  • 处理边界:当 i 或 j 为 0 或数组长度时,其左边或右边可能没有元素。这时我们可以把 L1, L2 视为负无穷大,把 R1, R2 视为正无穷大,这样大小比较的逻辑依然成立。

代码实现:
不太会写,学习一下g老师的代码

#include <stdio.h>
#include <limits.h> // 用于 INT_MIN 和 INT_MAX// 一个简单的宏来获取最大值和最小值,比引入 math.h 更轻量
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {// 确保 nums1 是较短的数组,这样可以减少二分查找的次数if (nums1Size > nums2Size) {return findMedianSortedArrays(nums2, nums2Size, nums1, nums1Size);}int m = nums1Size;int n = nums2Size;int low = 0, high = m;// 在较短的数组 nums1 上进行二分查找while (low <= high) {// partition1 是 nums1 的分割点int partition1 = low + (high - low) / 2;// partition2 是 nums2 的分割点,根据总长度的一半来计算int partition2 = (m + n + 1) / 2 - partition1;// 获取分割线左侧的最大值// 如果 partition1 为 0,说明 nums1 的左半部分为空,取负无穷int maxLeft1 = (partition1 == 0) ? INT_MIN : nums1[partition1 - 1];// 如果 partition2 为 0,说明 nums2 的左半部分为空,取负无穷int maxLeft2 = (partition2 == 0) ? INT_MIN : nums2[partition2 - 1];// 获取分割线右侧的最小值// 如果 partition1 等于 m,说明 nums1 的右半部分为空,取正无穷int minRight1 = (partition1 == m) ? INT_MAX : nums1[partition1];// 如果 partition2 等于 n,说明 nums2 的右半部分为空,取正无穷int minRight2 = (partition2 == n) ? INT_MAX : nums2[partition2];// 检查是否找到了完美的分割线if (maxLeft1 <= minRight2 && maxLeft2 <= minRight1) {// 如果总元素个数是偶数if ((m + n) % 2 == 0) {return (MAX(maxLeft1, maxLeft2) + MIN(minRight1, minRight2)) / 2.0;} else { // 如果总元素个数是奇数return (double)MAX(maxLeft1, maxLeft2);}} // 如果 nums1 左边的最大值大于了 nums2 右边的最小值// 说明 partition1 太大了,需要向左移动else if (maxLeft1 > minRight2) {high = partition1 - 1;} // 否则说明 partition1 太小了,需要向右移动else {low = partition1 + 1;}}// 如果程序运行到这里,说明输入数组不是有序的,按题目要求不会发生// 在实际工程中,这里应该抛出异常return -1.0; 
}// ------ 主函数用于测试 ------
int main() {// 测试用例 1: 奇数总长int nums1[] = {1, 3};int nums2[] = {2};double median1 = findMedianSortedArrays(nums1, 2, nums2, 1);printf("Test Case 1: Median is %f\n", median1); // 应该输出 2.0// 测试用例 2: 偶数总长int nums3[] = {1, 2};int nums4[] = {3, 4};double median2 = findMedianSortedArrays(nums3, 2, nums4, 2);printf("Test Case 2: Median is %f\n", median2); // 应该输出 2.5return 0;
}

运行结果:
在这里插入图片描述

复杂度分析:
时间复杂度:O(log(min(m,n)))
空间复杂度:O(1)
ok see you next time~

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

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

相关文章

无人机抗噪模块技术概述!

一、 技术要点1. 传感器数据融合与滤波&#xff08;解决感知噪声&#xff09;核心思想&#xff1a;单一传感器易受干扰且不全面&#xff0c;通过融合多种传感器&#xff08;IMU惯性测量单元、GPS、气压计、磁力计、视觉传感器、激光雷达等&#xff09;的数据&#xff0c;利用算…

Horse3D游戏引擎研发笔记(六):在QtOpenGL环境下,仿Unity的材质管理Shader绘制四边形

在上一篇笔记中&#xff0c;我们已经实现了基于QtOpenGL的BufferGeometry管理VAO和EBO绘制四边形的功能。这一次&#xff0c;我们将深入探讨材质管理系统的实现&#xff0c;包括Shader的加载与编译、材质的创建与使用&#xff0c;以及如何通过材质系统绘制带有自定义Shader效果…

MySQL-分库分表(Mycat)

目录 1.介绍​ 概述 拆分策略 垂直拆分​ 水平拆分​ 实现技术​ shardingJDBC: MyCat: 2.Mycat概述 环境准备​ 分片配置 schema.xml​ server.xml 启动服务​ 分片测试​ 3.MyCat配置 schema.xml​ schema标签 datanode标签 ​datahost标签​ rule.xml …

Dubbo 的 Java 项目间调用的完整示例

1. 项目结构假设项目分为三个模块&#xff1a;api&#xff1a;定义服务接口provider&#xff1a;服务提供者consumer&#xff1a;服务消费者2. 依赖配置在 pom.xml 中添加 Dubbo 和注册中心&#xff08;如 Nacos&#xff09;的依赖&#xff1a;<dependency><groupId&g…

Python进行中文分词

1. jieba库概述 jieba&#xff08;“结巴”&#xff09;是Python中最流行的中文分词库&#xff0c;采用基于前缀词典实现的高效分词算法&#xff0c;支持多种分词模式&#xff0c;是中文自然语言处理(NLP)的基础工具。 核心特性 精确模式&#xff1a;试图将句子最精确地切开&am…

JavaScript 性能优化实战:从原理到落地的完整指南

一、引言&#xff1a;为什么 JavaScript 性能优化至关重要&#xff1f;性能与用户体验的强关联数据支撑&#xff1a;加载延迟每增加 1 秒&#xff0c;用户转化率下降 7%&#xff08;来自 Google 研究&#xff09;核心痛点&#xff1a;现代 Web 应用中 JS 代码体积膨胀、运行时卡…

前端自动化部署

摘要&#xff1a;前端自动化部署是通过工具和流程自动化实现前端代码从开发完成到线上发布的全流程&#xff0c;减少人工操作、提高效率并降低出错风险。核心目标减少重复操作&#xff1a;自动化构建、测试、部署等步骤&#xff0c;替代手动上传服务器等低效方式。提升发布效率…

peewee中db.create_tables(tables, safe=True),safe=True作用

db.create_tables(tables, safeTrue) 中的 safeTrue 参数的作用是 防止在表已经存在的情况下引发错误。 具体来说&#xff1a; 当 safeTrue 时&#xff1a;Peewee 会在生成的 SQL 语句中加入 IF NOT EXISTS 子句&#xff08;例如&#xff1a;CREATE TABLE IF NOT EXISTS my_tab…

2025年计算机视觉与图像国际会议(ICCVI 2025)

2025年计算机视觉与图像国际会议| 视界创新&#xff0c;图领未来 2025年计算机视觉与图像国际会议&#xff08;ICCVI 2025&#xff09;将在中国东莞盛大召开。这不仅是一次汇聚全球顶尖科学家、工程师和学者的盛会&#xff0c;更是一个探索计算机视觉和图像处理领域前沿技术与未…

Temu美国站大规模扫号封店:虚假本土店遭批量封禁,如何规避?

2025年8月&#xff0c;Temu平台针对美国站再次掀起大规模扫号风暴。大量店铺因注册信息违规被判定为“高风险”&#xff0c;不仅店铺被冻结&#xff0c;商品也被下架并禁止补货。这一轮清扫&#xff0c;让不少依靠“资料店”快速起盘的卖家遭遇重创。事实上&#xff0c;Temu的风…

航空发动机叶片yolov8模型训练和转换(包含适配rk3588-pt转onnx转rknn)

前言&#xff1a; 1.训练在windows进行&#xff0c;因为电脑没有显卡&#xff0c;所以纯cpu训练&#xff0c;生成pt后转onnx 2.onnx转需要在Ubuntu虚拟机上运行 3.数据集标定快捷键 &#xff08;模型训练时不需要&#xff09;官方地址和下载pt权重&#xff1a;链接&#xff…

PyTorch如何修改模型(魔改)?/替换模型,一般除了注意输入输出一致,还有其他要修改的吗?

一、PyTorch如何修改模型&#xff08;魔改&#xff09;? 可以参考这个链接&#xff0c;看了一下还不错&#xff1a; PyTorch如何修改模型&#xff08;魔改&#xff09;_模型魔改-CSDN博客 二、替换模型&#xff0c;一般除了注意输入输出一致&#xff0c;还有其他要修改的吗?…

Pycharm Debug详解

Pycharm Debug详解看这个工具栏就是 PyCharm 调试器的“步进/断点”按钮区。常用按钮和作用&#xff08;从左到右一般是这些&#xff09;&#xff1a; Resume / 继续运行&#xff08;F9&#xff09;&#xff1a;从当前断点继续跑&#xff0c;直到下一个断点或程序结束。Step Ov…

将SSL配置迁移到Nacos的步骤

将SSL配置迁移到Nacos的步骤 要将SSL配置从本地application.yml迁移到Nacos配置中心&#xff0c;需要完成以下几个步骤&#xff1a; 1. 创建Nacos配置文件 在Nacos中创建一个新的配置文件&#xff08;例如application-ssl.yml&#xff09;&#xff0c;内容如下&#xff1a; ser…

HTTP请求参数类型及对应的后端注解

在Java后端开发中&#xff0c;HTTP请求的不同部分需要使用不同的注解来处理。以下是四种主要请求参数类型及其对应的Spring注解&#xff1a;1. 请求头(Headers)​​位置​​&#xff1a;HTTP请求的头部信息​​常用场景​​&#xff1a;认证信息(Token)、客户端信息、内容类型等…

服务器硬件电路设计之 SPI 问答(一):解密 SPI—— 从定义到核心特性

在服务器硬件电路设计中&#xff0c;SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外设接口&#xff09;是一种关键的通信总线。它由摩托罗拉公司开发&#xff0c;是全双工、同步串行通信总线&#xff0c;主要用于微控制器与外围设备之间的通信&#xff0c;凭借…

【2025CVPR-目标检测方向】OW-OVD:统一的开放世界和开放词汇对象检测

研究背景与动机​ ​问题​:传统目标检测器(封闭集)需预定义所有类别,无法适应动态开放环境。现有研究多独立解决开放词汇检测(OVD)或开放世界检测(OWOD),未结合两者优势: ​OVD​:通过文本-视觉嵌入匹配实现零样本泛化,但无法主动发现未知对象。 ​OWOD​:可主动…

基于Python的就业信息推荐系统 Python+Django+Vue.js

本文项目编号 25011 &#xff0c;文末自助获取源码 \color{red}{25011&#xff0c;文末自助获取源码} 25011&#xff0c;文末自助获取源码 目录 一、系统介绍二、系统录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状 六、核心代码6.1 查询数据6.2 新…

el-date-picker type=daterange 日期范围限制

html &#xff08;组件&#xff1a;element-ui&#xff09;重点&#xff1a; :picker-options"pickerOptions"<template><el-date-pickerv-model"form.dateRange"type"daterange" value-format"yyyy-MM-dd"range-separator&q…

【38页PPT】关于5G智慧园区整体解决方案(附下载方式)

篇幅所限&#xff0c;本文只提供部分资料内容&#xff0c;完整资料请看下面链接 https://download.csdn.net/download/2501_92808811/91694207 资料解读&#xff1a;《关于5G智慧园区整体解决方案》 详细资料请看本解读文章的最后内容。 智慧园区行业理解与建设目标 智慧园…