【力扣算法02】之寻找两个正序数组的中位数 - python

文章目录

  • 问题描述
    • 示例 1
    • 示例2
    • 提示
  • 解题思路
  • 代码分析
  • 完整代码
  • 运行效果及示例代码
    • 示例代码1
      • 效果图
    • 示例代码2
      • 效果图
  • 完结

问题描述

在这里插入图片描述

给定两个大小分别为 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

提示

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

解题思路

在这里插入图片描述

  1. 定义了一个名为Solution的类,它包含了一个名为findMedianSortedArrays的方法,这个方法用于查找两个已排序数组的中位数。
  2. 方法参数包括self(表示方法所属的类实例)、nums1nums2(两个已排序的数组)。
  3. 首先,通过比较两个数组的长度,确保nums1是较短的数组,将较长的数组赋值给nums2,以简化后续操作。
  4. 获取nums1nums2的长度分别赋值给变量mn
  5. 初始化变量leftright,分别表示二分查找的起始左右边界,初始值为0m
  6. 初始化变量median1median2,分别表示中位数的左侧和右侧值,初始值为0
  7. 进入while循环,循环条件为left <= right,即当左边界小于等于右边界时,进行循环。
  8. 在循环中,首先计算出两个数组的当前的分隔点partition1partition2,其中partition1nums1的分隔点,partition2nums2的分隔点。
  9. 根据分隔点,计算出四个值:maxLeft1minRight1maxLeft2minRight2
    • maxLeft1表示nums1左侧最大的值,如果partition1为0,则取float('-inf')表示负无穷大;否则,取nums1[partition1-1]
    • minRight1表示nums1右侧最小的值,如果partition1等于m,则取float('inf')表示正无穷大;否则,取nums1[partition1]
    • maxLeft2表示nums2左侧最大的值,如果partition2为0,则取float('-inf')表示负无穷大;否则,取nums2[partition2-1]
    • minRight2表示nums2右侧最小的值,如果partition2等于n,则取float('inf')表示正无穷大;否则,取nums2[partition2]
  10. 接下来通过比较四个值的大小关系,判断当前的分隔点是否符合中位数的条件:
    • 如果满足条件maxLeft1 <= minRight2maxLeft2 <= minRight1,则说明找到了符合中位数条件的分隔点。
    • 如果(m + n)为偶数,则中位数为(max(maxLeft1, maxLeft2) + min(minRight1, minRight2)) / 2.0
    • 如果(m + n)为奇数,则中位数为max(maxLeft1, maxLeft2)
    • 返回计算得到的中位数。
  11. 如果maxLeft1 > minRight2,说明当前的分隔点在nums1中太靠右,需要将右边界right更新为partition1 - 1
  12. 否则,说明当前的分隔点在nums1中太靠左,需要将左边界left更新为partition1 + 1
  13. 循环结束后,如果没有找到符合条件的分隔点,则抛出ValueError异常,表示输入无效。

代码分析

class Solution(object):def findMedianSortedArrays(self, nums1, nums2):if len(nums1) > len(nums2):nums1, nums2 = nums2, nums1

这部分代码定义了一个名为Solution的类,并在该类中定义了一个名为findMedianSortedArrays的方法。方法接受两个已排序的数组nums1nums2作为输入。如果nums1的长度大于nums2的长度,则交换两个数组,以确保nums1是较短的数组。

        m, n = len(nums1), len(nums2)left, right = 0, mmedian1, median2 = 0, 0

这部分代码初始化了一些变量。mn分别表示nums1nums2的长度。leftright分别表示二分查找的起始左右边界,初始值为0mmedian1median2分别表示中位数的左侧和右侧值,初始值为0

        while left <= right:partition1 = (left + right) // 2partition2 = (m + n + 1) // 2 - partition1maxLeft1 = 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]

这部分代码进入了一个while循环,该循环用于执行二分查找。循环条件是left <= right,即当左边界小于等于右边界时,进行循环。

在循环中,首先计算出两个数组的当前的分隔点partition1partition2partition1nums1的分隔点,partition2nums2的分隔点。

然后,通过分隔点计算出四个值:maxLeft1minRight1maxLeft2minRight2

  • maxLeft1表示nums1左侧最大的值,如果partition1为0,则取float('-inf')表示负无穷大;否则,取nums1[partition1-1]
  • minRight1表示nums1右侧最小的值,如果partition1等于m,则取float('inf')表示正无穷大;否则,取nums1[partition1]
  • maxLeft2表示nums2左侧最大的值,如果partition2为0,则取float('-inf')表示负无穷大;否则,取nums2[partition2-1]
  • minRight2表示nums2右侧最小的值,如果partition2等于n,则取float('inf')表示正无穷大;否则,取nums2[partition2]
            if maxLeft1 <= minRight2 and maxLeft2 <= minRight1:if (m + n) % 2 == 0:median1 = max(maxLeft1, maxLeft2)median2 = min(minRight1, minRight2)return (median1 + median2) / 2.0else:median1 = max(maxLeft1, maxLeft2)return median1elif maxLeft1 > minRight2:right = partition1 - 1else:left = partition1 + 1

在循环体中,根据四个值的大小关系判断当前的分隔点是否符合中位数的条件。如果满足条件maxLeft1 <= minRight2maxLeft2 <= minRight1,则说明找到了符合中位数条件的分隔点。

如果(m + n)为偶数,则中位数为(max(maxLeft1, maxLeft2) + min(minRight1, minRight2)) / 2.0

如果(m + n)为奇数,则中位数为max(maxLeft1, maxLeft2)

如果找到了中位数,直接返回中位数。

如果maxLeft1 > minRight2,说明当前的分隔点在nums1中太靠右,需要将右边界right更新为partition1 - 1

否则,说明当前的分隔点在nums1中太靠左,需要将左边界left更新为partition1 + 1

        raise ValueError("Invalid input")

循环结束后,如果没有找到符合条件的分隔点,抛出ValueError异常,表示输入无效。

代码通过二分查找的方式在两个已排序数组中寻找中位数,时间复杂度为O(log(min(m, n))),其中m和n分别为两个数组的长度。

完整代码

在这里插入图片描述

class Solution(object):def findMedianSortedArrays(self, nums1, nums2):if len(nums1) > len(nums2):nums1, nums2 = nums2, nums1# 如果nums1的长度大于nums2的长度,则交换两个数组,使得nums1成为较短的数组m, n = len(nums1), len(nums2)left, right = 0, mmedian1, median2 = 0, 0# m和n分别表示nums1和nums2的长度,left和right初始化为0和m,median1和median2初始化为0while left <= right:partition1 = (left + right) // 2partition2 = (m + n + 1) // 2 - partition1# 计算当前的分割点partition1和partition2# 使用二分查找的方法查找中位数maxLeft1 = float('-inf') if partition1 == 0 else nums1[partition1 - 1]minRight1 = float('inf') if partition1 == m else nums1[partition1]# 计算nums1中左侧的最大值和右侧的最小值maxLeft2 = float('-inf') if partition2 == 0 else nums2[partition2 - 1]minRight2 = float('inf') if partition2 == n else nums2[partition2]# 计算nums2中左侧的最大值和右侧的最小值if maxLeft1 <= minRight2 and maxLeft2 <= minRight1:if (m + n) % 2 == 0:median1 = max(maxLeft1, maxLeft2)median2 = min(minRight1, minRight2)return (median1 + median2) / 2.0# 如果符合中位数条件,且总长度为偶数,返回两个中间值的平均数else:median1 = max(maxLeft1, maxLeft2)return median1# 如果符合中位数条件,且总长度为奇数,返回较大的中间值elif maxLeft1 > minRight2:right = partition1 - 1# 当前分割点在nums1中太靠右,更新右边界else:left = partition1 + 1# 当前分割点在nums1中太靠左,更新左边界raise ValueError("Invalid input")# 没有找到符合条件的分割点,抛出异常表示输入无效

运行效果及示例代码

示例代码1

nums1 = [1, 3]
nums2 = [2]
solution = Solution()
median = solution.findMedianSortedArrays(nums1, nums2)
print("示例1的中位数为:", median)

效果图

在这里插入图片描述

示例代码2

nums1 = [1, 2]
nums2 = [3, 4]
solution = Solution()
median = solution.findMedianSortedArrays(nums1, nums2)
print("示例2的中位数为:", median)

效果图

在这里插入图片描述

完结

在这里插入图片描述

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

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

相关文章

每天几道高频算法题-DAY1

从今天开始 每天做几道高频算法题 备战秋招 如果有算法还没刷题的(买不起LeetCode会员的) 可以和我一起刷 题目一 给定一个有序数组arr,从左到右依次表示X轴上从左往右点的位置,给定一个正整数K&#xff0c;返回如果有一根长度为K的绳子&#xff0c;最多能盖住几个点绳子的边…

820. 递归求斐波那契数列

链接&#xff1a; 原题 题目&#xff1a; 请使用递归的方式求斐波那契数列的第 nn 项&#xff0c;下标从1开始。 斐波那契数列&#xff1a;1,1,2,3,5…1,1,2,3,5…&#xff0c;这个数列从第 33 项开始&#xff0c;每一项都等于前两项之和 输入格式 共一行&#xff0c;包含整数 …

卷积神经网络

目录 1、卷积运算 2、使用卷积运算实现垂直边缘检测 3、区分正边、负边 4、计算输出矩阵大小 5、边缘填充方法 6、卷积步长 7、三维卷积 8、单层卷积网络 9、卷积层的各种标记 10、简单卷积网络 11、池化层 12、卷 积 神 经 网 络 示 例 1、卷积运算 使用灰度图像…

保姆级指针进阶教程——【C语言】

在之前的博客中&#xff0c;我简单的介绍了什么是指针、指针的大小、运算、二级指针等等一些指针的基础知识&#xff0c;接下来我将带大家深入的了解一下指针&#xff0c;保证让大家对指针有更深刻的理解。 目录 字符指针 指针数组 数组指针 数组名VS&数组名 数组指针的…

第十二章 elk

1、ELK可以帮助我们解决哪些问题 日志分布在多台不同的服务器上,业务一旦出现故障,需要一台台查看日志 单个日志文件巨大,无法使用常用的文本工具分析,检索困难; 2、架构设计分析 Filebeat和Logstash ELK架构中使用Logstash收集、解析日志,但是Logstash对内存、cpu、i…

Spring IOC - Bean的扫描

Component及其衍生注解&#xff1a;Configuration、Controller、Service、Repository标记的类&#xff0c;被Spring IOC扫描到后&#xff0c;即可被容器管理起来。其原理基本涵盖在AnnotationConfigApplicationContext构造函数体的三行代码里。 public AnnotationConfigApplic…

6阶高清视频滤波驱动MS1681

MS1681 是一个单通道视频缓冲器&#xff0c;它内部集成6dB 增益的轨到轨输出驱动器和6 阶输出重建滤波器。MS1681 的-3dB 带宽为35MHz&#xff0c;压摆率为160V/us。MS1681 比无源LC 滤波器与外加驱动的解决方案能提供更好的图像质量。它单电源供电范围为2.5V 到5.5V&#xff0…

检验样本正态性

简介 在统计学中很多推论与正态分布有关&#xff0c;并且很多统计量构造为满足正态分布的形式&#xff0c;很多分布在特定条件近似于正态分布。因此&#xff0c;在统计推断中经常需要判断样本的正态性。本文介绍一些常用的方法。 环境和数据准备&#xff1a; import numpy a…

【Go】Go 语言教程--GO语言数组(十一)

往期回顾&#xff1a; Go 语言教程–介绍&#xff08;一&#xff09;Go 语言教程–语言结构&#xff08;二&#xff09;Go 语言教程–语言结构&#xff08;三&#xff09;Go 语言教程–数据类型&#xff08;四&#xff09;Go 语言教程–语言变量&#xff08;五&#xff09;Go …

Echarts使用,大数据量时,折线图曲线Y轴取值刻度不正确

如下图&#xff0c;当数据量过大时&#xff0c;会出现数值对应Y轴刻度显示不正确问题。 ​​​​​​​ 可检查配置项是否存在sampling字段 option {series: [{data: [...],type: line,smooth: true,symbolSize: 0,sampling: "average", // 注意此行}] }; samplin…

fpga下载程序到flash后无法在重新上电后自动加载程序

是器件的约束配置问题&#xff0c;这是正点原子artix7用的器件配置&#xff0c;如果不用就有问题 # 器件 set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] set_property CONFIG_MODE SPIx4 [current_design] set_property BITST…

WH5097D有源矩阵驱动的Mini LED背光应用方案

Miniled技术为lcd的全面升级版&#xff0c;Miniled的背光层在单位面积内可以容纳更多LED&#xff0c;从而大大提高背光源数量&#xff0c;因此可以进行区域亮度调节的设计&#xff0c;从而在个别区域实现关闭led从而达到完全的黑色&#xff0c;不仅减小了功耗&#xff0c;而且由…