当前位置: 首页 > news >正文

力扣Leetcode:4. 寻找两个正序数组的中位数(Python)

题目描述

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

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

题解

由于时间复杂度要求,所以要用二分查找(看到log与有序数组,所以必然是二分)、且不要考虑合并两个有序数组为一个数组(只要合并了,复杂度至少是O(m+n))。

一个直观的思路是,将该问题转换为求第k大的数的问题。但由于这儿有两个有序数组A与B,因此我们首先比较A[k/2]与B[k - k/2 - 1]这两个元素的大小,较小者及其同一数组内之前的元素中一定不会存在目标元素,可以直接去掉——我们的“二分”就体现在这里。相较于“每次保留一半”,我们这里的做法是“每次排除一半”。

为什么下标pos1 = k/2对应下标pos2 = k - k/2 - 1呢?这是因为,如果A[pos1] < B[pos2], 那么A[l1 … pos1]中必然不存在第k大的数字!

需要注意的细节有:

  • 如果所有元素为偶数个,需要找两个位置之后求平均值。
  • 如果一个数组内没有那么多元素,此时直接将该数组内最后一个元素与另一数组内的对应位置(第一个数组内的位置i对应第二个数组内的位置k-i-1,这两个位置的元素如果相等,那它们刚好是目标位置)元素比较。
  • k到底指的是第k个、还是下标为k,需要想清楚。我在代码里的k指的下标为k。
  • k是绝对位置还是相对位置,需要想清楚。我在代码里的k为相对位置,需要加上l之后才表示真实位置。

边界条件为:

  • k为1时,仅需比较一次之后返回较小者即可。
  • 当其中一个数组为空时,只需要在另一数组中返回位置k的元素即可。

代码(Python)

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        m, n = len(nums1), len(nums2)
        return (self.binary_find(nums1, 0, m-1, nums2, 0, n-1, (m+n)//2 - 1) +
                self.binary_find(nums1, 0, m-1, nums2, 0, n-1, (m+n)//2)) / 2 if (m+n) % 2 == 0 \
            else self.binary_find(nums1, 0, m-1, nums2, 0, n-1, (m+n)//2)

    def binary_find(self, nums1, l1, r1, nums2, l2, r2, k) -> float:
        if l1 > r1:
            return nums2[l2 + k]
        elif l2 > r2:
            return nums1[l1 + k]
        if k == 0:
            return min(nums1[l1], nums2[l2])
        if (r1 - l1) < (r2 - l2):
            pos1 = k//2 if l1+k//2 <= r1 else r1-l1
            pos2 = k - pos1 - 1
        else:
            pos2 = k//2 if l2+k//2 <= r2 else r2-l2
            pos1 = k - pos2 - 1
        if nums1[l1 + pos1] == nums2[l2 + pos2]:
            return nums1[l1 + pos1]
        elif nums1[l1 + pos1] < nums2[l2 + pos2]:
            return self.binary_find(nums1, l1 + pos1 + 1, r1, nums2, l2, r2, k - (pos1 + 1))
        else:
            return self.binary_find(nums1, l1, r1, nums2, l2 + pos2 + 1, r2, k - (pos2 + 1))

相关文章:

  • Smart Client Case Study Source Code Download from MSDN China
  • 力扣Leetcode:5. 最长回文子串(Python)
  • 古诗词推荐(一):春风十里扬州路,卷上珠帘总不如
  • 终于签完了
  • 古诗词推荐(二):若似月轮终皎洁,不辞冰雪为卿热
  • 腾讯面经zz
  • 力扣Leetcode:10. 正则表达式匹配(Python)
  • 从《关于跳槽的切身体会(转)》谈转载文章的职业道德!!!
  • 力扣Leetcode:11. 盛最多水的容器(Python、Java)
  • 劝学诗整理:安居不用架高堂,书中自有黄金屋。
  • 服务器群集:Windows Server 2003 备份和恢复的最佳做法
  • 力扣Leetcode:15. 三数之和(Python)
  • 忙了一下午
  • 力扣Leetcode:17. 电话号码的字母组合(Python)
  • 新的生活:)
  • 分享的文章《人生如棋》
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • CSS魔法堂:Absolute Positioning就这个样
  • IndexedDB
  • spark本地环境的搭建到运行第一个spark程序
  • spring security oauth2 password授权模式
  • SSH 免密登录
  • vue 个人积累(使用工具,组件)
  • 闭包--闭包之tab栏切换(四)
  • 多线程事务回滚
  • 经典排序算法及其 Java 实现
  • 区块链分支循环
  • 王永庆:技术创新改变教育未来
  • 用Visual Studio开发以太坊智能合约
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • !!Dom4j 学习笔记
  • $.each()与$(selector).each()
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (C语言)字符分类函数
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (poj1.3.2)1791(构造法模拟)
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (二)JAVA使用POI操作excel
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (一)基于IDEA的JAVA基础10
  • (转)重识new
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .dwp和.webpart的区别
  • .NET CF命令行调试器MDbg入门(一)
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .NET Micro Framework初体验(二)
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET牛人应该知道些什么(2):中级.NET开发人员
  • .sh
  • /etc/sudoers (root权限管理)
  • @RunWith注解作用
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • [《百万宝贝》观后]To be or not to be?
  • [Android 13]Input系列--获取触摸窗口