LeetCode-4题解 寻找两个正序数组的中位数

news2024/11/26 15:27:01

文章目录

  • LeetCode-4[题解] 寻找两个正序数组的中位数
    • 问题描述
    • 样例
    • 解析
      • 1 常规做法
      • 2 二分+K-th Number解法
    • 代码

LeetCode-4[题解] 寻找两个正序数组的中位数

问题描述

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

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

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

样例

示例 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

解析

1 常规做法

常规做法很简单,虽然不满足题意,但是一定是最先想到的:

  1. 先归并排序在直接拎出中位数——时间复杂度 O ( m + n ) O(m+n) O(m+n),空间复杂度 O ( m + n ) O(m+n) O(m+n)
  2. 通过这两个数组可以知道整个数组的最小值/最大值,删除半个数组就可以找到中位数——时间复杂度 O ( m + n ) O(m+n) O(m+n),空间复杂度 O ( 1 ) O(1) O(1)

不满足题意的方法只能说是提供思路

2 二分+K-th Number解法

在题目要求时间复杂度在O(log (m+n)) 后,我们可以先整理出几个思路:

  1. 一定不能做任何遍历的操作:排序、移动指针。
  2. 我们已知的条件有什么?两个数组分别的最小值/最大值、综合后数组的最大值/最小值。
  3. 时间要求在log范围内,我自然就会想到二分。

在整理出这三点后我就陷入了误区,我一直想要用二分探索找到中位数的区间,但怎么都想不出来。~~通过大佬的一点小小启发,~~其实通过引入K-th Number的思想就可以解决这个问题。

  • 思路:假如我们要在 m + n m+n m+n个数中找到中位数,等价于我们要找到第 K = ⌊ m + n + 1 2 ⌋ K = {\lfloor \frac{m+n+1}{2} \rfloor} K=2m+n+1小的数(如果是偶数只要再往后找一个就行)。
  • 倘若我们要找到第 K K K个数,我们应该将前面的 K − 1 K-1 K1个数全部去除。

为了保证时间复杂度合适,自然不能像常规第二种解法一样一个一个删除,而是使用二分的思想。但是这个二分有点难考虑到:通过比较两个数列中第 ⌊ K / 2 ⌋ {\lfloor K / 2 \rfloor} K/2个数的大小,一定能删掉较小数列中的前 ⌊ K / 2 ⌋ {\lfloor K / 2 \rfloor} K/2个数。为什么呢?下面我们分情况考虑一下:

  1. 若第K个数不在其中一个数列的前 ⌊ K / 2 ⌋ {\lfloor K / 2 \rfloor} K/2个中:

  2. 若在前 ⌊ K / 2 ⌋ {\lfloor K / 2 \rfloor} K/2个中:

  3. 当然我们还要考虑一下特殊情况,超出范围则退到最远可比较的位置:

根据上述三种情况,我们一定在删除过程中不会删掉第 K K K个数。并且循环结束后我们可以将情况分成几种:

  1. 只剩一个数列:这个时候当前 K K K可能大于 1 1 1(由于好算,我们在代码直接判出),找到数列删掉的位置后面第 K K K个就好。
  2. 剩两个数列:这个时候 K K K一定等于 1 1 1(否则循环一定继续),找到当前两个数列的前两个数就好了(要注意考虑两个数组剩余数的个数,防止数组越界)。

这样就好啦,总结一下:

  1. 首先通过前 ⌊ K / 2 ⌋ {\lfloor K / 2 \rfloor} K/2个数的理论,删除数组直到 K = 1 K=1 K=1或只剩一条数组。
  2. 然后分类讨论,若只有一条数组就找到目前第 K K K个数,两条数组就找到最小的两个数就好。

代码

总体来说不太优雅,因为最后讨论的情况比较多,别的大佬代码应该会好看许多

class Solution {
public:
    pair<int, int> my_min(int a, int b1, int b2) {
        if (a < b1) return {a, b1};
        else return {b1, min(a, b2)};
    }
    pair<int, int> my_min(int a1, int a2, int b1, int b2) {
        if (a1 < b1) return {a1, min(b1, min(a2, b2))};
        else return {b1, min(a1, min(a2, b2))};
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int len1 = nums1.size(), len2 = nums2.size(); // 两个数组的长度
        int k = (len1 + len2 + 1) / 2, odd = (len1 + len2) & 1; // 第k小数、奇偶性
        int l1 = 0, l2 = 0; // 数组左端点
        while (k > 1 && l1 < len1 && l2 < len2) {
            int len = k / 2; // 探测的长度

            // 一边超出限制
            if (l1 + len > len1 || l2 + len > len2) len = min(len1 - l1, len2 - l2);

            // 探测
            if (nums1[l1 + len - 1] < nums2[l2 + len - 1]) l1 += len;
            else l2 += len;
            k -= len;
        }

        if (l1 == len1) return odd ? nums2[l2+k-1] : 1.0 * (nums2[l2+k-1] + nums2[l2+k]) / 2;
        if (l2 == len2) return odd ? nums1[l1+k-1] : 1.0 * (nums1[l1+k-1] + nums1[l1+k]) / 2;
        if (odd) return min(nums1[l1], nums2[l2]);
        else if (len1 - l1 < 2 && len2 - l2 < 2) {
            return 1.0 * (nums1[l1] + nums2[l2]) / 2;
        } else if (len1 - l1 < 2) {
            pair<int, int> mn = my_min(nums1[l1], nums2[l2], nums2[l2+1]);
            return 1.0 * (mn.first + mn.second) / 2;
        } else if (len2 - l2 < 2) {
            pair<int, int> mn = my_min(nums2[l2], nums1[l1], nums1[l1+1]);
            return 1.0 * (mn.first + mn.second) / 2;
        } else {
            pair<int, int> mn = my_min(nums1[l1], nums1[l1+1], nums2[l2], nums2[l2+1]);
            return 1.0 * (mn.first + mn.second) / 2;
        }
    }
};

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

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

相关文章

《Hand Keypoint Detection in Single Images using Multiview Bootstrapping》及模型推理

论文&#xff1a;《Hand Keypoint Detection in Single Images using Multiview Bootstrapping》2017 链接&#xff1a;1704.07809.pdf (arxiv.org) code&#xff1a;Hand Keypoint Detection using Deep Learning and OpenCV | LearnOpenCV 论文略读 1.Introduction In th…

AntDB数据库荣获2023年中国信创产业拳头奖“2023年中国信创数据库卓越品牌”

近日&#xff0c;由全球新经济产业第三方数据挖掘和分析机构iiMedia Research&#xff08;艾媒咨询&#xff09;主办的“2023年&#xff08;第2届&#xff09;中国信创产业大会”在广州圆满落幕。大会现场揭晓了“2023年中国信创产业拳头奖”。AntDB数据库从众多参评产品中脱颖…

研发为底、生态为径、AI为翼——全国一体化算力算网调度平台正式发布

GPU | COMPUTEX | 算力 | GPU服务器 英伟达 | GH200 | 一体化算力算网调度平台 近年来&#xff0c;人工智能硬件、软件算法以及应用场景的丰富度不断增加&#xff0c;算法模型参数也不断增加&#xff0c;这带动了对数据中心并行计算算力的需求。因此&#xff0c;AI、高性能计算…

升级后,配置文件被清空,导致无法开启WiFi

root cause&#xff1a; /data/vendor/wifi/wpa/wpa_supplicant.conf 是0字节&#xff0c;导致wpa_supplicant_init_iface缺少”p2p_disabled1“的配置就会在走错flow到p2p wpa_supplicant_init_iface 》wpas_p2p_init 从而在HidlManager::registerInterface 进入 if (isP2pIf…

EDLA协议授权,谷歌GMS认证,设备申请EDLA协议过认证,谷歌GMS EDLA协议

一、EDLA协议跟MADA协议以及GMS认证有什么关联&#xff1f;AER又是什么&#xff1f;车机使用什么协议申请GMS认证&#xff1f; GMS全称是Google Mobile Service(即谷歌移动服务)&#xff0c;GMS认证简单来说就是使用安卓系统的移动设备在经过谷歌的一系列测试后取得谷歌的认可&…

为什么学深度学习的同学都需要懂高性能计算?

深度学习作为人工智能领域的热门技术&#xff0c;正以惊人的速度推动着科学和工业的进步。然而&#xff0c;随着深度学习模型的不断复杂化和数据量的急剧增长&#xff0c;传统的计算资源已经无法满足其高效运算的需求。因此&#xff0c;对于学习深度学习的同学来说&#xff0c;…

Pod 的 phase 和 conditions 的区别

目录 前言 PodStatus对象 pod 的 phase 字段 phase 作用 有哪些 phase pod 的 conditions 字段 pod 有了 phase&#xff0c;为什么还要有 conditions pod 的 conditions 的作用 pod 的 conditions 分类 conditions设计原则 condition字段内容 前言 K…

高颜值测试报告- XTestRunner

基于unittest框架现代风格测试报告。 特点 漂亮测试报告让你更愿意编写测试。支持单元、Web UI、API 各种类型的测试。支持Selenium运行失败/错误自动截图。支持失败重跑。支持标签黑、白名单。支持发邮件功能。支持多语言en、zh-CN 等。支持HTML/XML不同格式的报告。 安装 …

ADG-rac备库的问题处理

第一次配置rac to rac的的adg&#xff0c;ADG过程就不叙述了&#xff0c;备库同步完成后&#xff0c;使用srvctl加入集群时未报错&#xff0c;但是使用crsctl status res -t查看状态时&#xff0c;发现了问题&#xff0c;如下图 ASM1:/home/gridhydb1> crsctl status res -…

达梦数据库DSC集群搭建:两节点与多节点(三节点)集群搭建

目录 说明... 4 两节点集群搭建... 5 一、创建共享磁盘... 6 1、DMDSC01添加硬盘... 6 2、DMDSC02添加共享磁盘... 8 二、搭建DMDSC集群... 12 1、安装完成数据库配置资源限制... 12 2、添加用户变量... 13 3、共享磁盘分区... 14 4、新建udev规则文件-裸设备绑定...…

如何将PDF转换为Excel?这4个方法请收好

PDF&#xff08;便携式文档格式&#xff09;因其安全且易于访问而广泛用于在线共享和存档文档。但是&#xff0c;很多时候您可能需要从 PDF 文档中提取数据以在 Excel 中使用它。这是将 PDF 转换为 Excel 发挥作用的地方。在本文中&#xff0c;我们将探讨将 PDF 文件转换为 Exc…

HarmonyOS学习路之开发篇—Java UI框架(自定义组件与布局 一)

HarmonyOS提供了一套复杂且强大的Java UI框架&#xff0c;其中Component提供内容显示&#xff0c;是界面中所有组件的基类。ComponentContainer作为容器容纳Component或ComponentContainer对象&#xff0c;并对它们进行布局。 Java UI框架也提供了一部分Component和ComponentC…

linux系统总结

linux系统总结&#xff1a; linux系统总结 一、网络&#xff1a;1.七层模型&#xff1a;2.三次握手&#xff0c;四次挥手&#xff1a;3.网络层&#xff1a;ARP&#xff0c;icmp4.总结tcp和udp的不同&#xff1a;5.端口号的作用&#xff1a;6.VRRP的原理&#xff1a;SNAT DNAT7…

论文解读 | 超越人类智慧!类脑多模态混合神经网络助力机器人精准定位

原创 | 文 BFT机器人 01 研究内容 这篇论文的研究内容是基于大脑启发的多模态混合神经网络&#xff0c;用于机器人地点识别。研究人员设计了一个名为NeuroGPR的系统&#xff0c;该系统可以模拟大脑的多模态感知机制&#xff0c;从传统和神经形态传感器中编码和整合多模态线索&a…

消息队列的基本概念

每种消息队列都有自己的一套消息模型&#xff0c;像队列&#xff08;Queue&#xff09;、主题&#xff08;Topic&#xff09;或是分区&#xff08;Partition&#xff09;这些名词概念&#xff0c;在每个消息队列模型中都会涉及一些&#xff0c;含义还不太一样。 为什么出现这种…

1.8C++流提取运算符重载

C流提取运算符重载 在 C中&#xff0c;流提取运算符&#xff08;>>&#xff09;是用于从流中提取数据的运算符。 C中的流提取运算符可以被重载&#xff0c;使得程序员可以自定义输入对象的方式&#xff0c;更方便地输入自定义的数据类型&#xff0c;也可以使得输入更加…

阿里云轻量应用服务器和云服务器ECS区别(终于懂了)

阿里云服务器ECS和轻量应用服务器有什么区别&#xff1f;云服务器ECS是明星级云服务器&#xff0c;轻量应用服务器可以理解为简化版的云服务器ECS&#xff0c;轻量适用于单机应用&#xff0c;云服务器ECS适用于集群类高可用高容灾应用&#xff0c;阿里云百科来详细说下阿里云轻…

dbGet 快速学习教程

dbGet是innovus/encounter工具自带的"database access command"命令中的一部分&#xff0c;它几乎可以用来获取设计相关的一切信息。 输入dbGet 按[Tab]键&#xff0c;能看到三个选项&#xff0c;分别是head / top /selected。这三个选项所代表的意义如下: head --…

Vue3对于一个前端来讲意味着什么?

最近很多技术网站&#xff0c;讨论的最多的无非就是Vue3了&#xff0c;大多数都是Composition API和基于Proxy的原理分析。但是今天想着跟大家聊聊&#xff0c;Vue3对于一个低代码平台的前端更深层次意味着什么&#xff1f; 首先&#xff0c;Vue是前端三大主流框架之一&#xf…

python,如何设置定时执行python代码-windows本地

最近写了一个python小程序&#xff0c;希望能每天定时执行&#xff0c;但是又不想用jenkins这样的工具&#xff0c;后来发现windows本地就可以设置&#xff0c;而且很好用&#xff0c;具体步骤如下&#xff1a; 首先&#xff0c;需确保本地python代码已编写好&#xff0c;环境…