算法/编程练习:两个有序数组的中位数

2024-09-04 18:32

本文主要是介绍算法/编程练习:两个有序数组的中位数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

算法/编程练习:两个有序数组的中位数

题目来自LeetCode:
https://leetcode-cn.com/problems/median-of-two-sorted-arrays/

题目:

给定两个大小为 n1 和 n2 的有序(升序)数组 nums1 和 nums2 ,
找出这两个有序数组的中位数mid。
要求算法的时间复杂度为 O(log(m + n))。
例如,
输入:  nums1 = [1, 3, 5, 7, 9],  nums2 = [2, 4, 6, 8, 10, 11]
输出:  mid=6

思路:

记总的数组长度为 N = n1 + n2,则两个数组中小于等于mid的数有 N_lef = int(N/2)个 。
假设用索引 idx1 将 nums1 分为左右两部分,用索引 idx2 将 nums2 分为左右两部分,
若此时 nums1 和nums2的左边部分共同构成 mid 的左边,
nums1 和 nums2 的右边部分共同构成 mid 的右边,
那么 idx1 和 idx2 应满足等量约束 idx2 + idx1 + 1 = N_left。
根据中位数的定义,nums1 左边部分的最大值不能大于 num2 右边部分的最小值,
nums2 的切分同理。
因此只需要从 nums1 的最大索引开始遍历,找出 合适的 idx1 和 idx2 即可。  即:
# idx1把nums1分为左右两部分:
nums1_left = nums1[0:idx1+1]
nums1_right = nums1[idx1+1:]
# idx2把nums2分为左右两部分:
nums2_left = nums2[0:idx2]
nums2_right = nums2[idx2:]
# 能正确划分nums1和nums2从而找到mid的idx1和idx2应满足
idx2 = N_left - (idx1+1) # 且
nums1[idx1] <= nums2[idx2]

Python代码:

def Find2OrderedListMid(nums1, nums2):if not isinstance(nums1, list) or not isinstance(nums2, list):print('请输入两个列表!')return None​n1, n2 = len(nums1), len(nums2)N = n1 + n2N_left = int(N/2) # 合并数列中,中位数前面的数的个数odd = False if N % 2 == 0 else True# 代码简化处理,不考虑有数组长度为0的情况下if n1 == 0 or n2 == 0:print('需要保证两个数组的长度均大于0!')return None​​# 保持nums1的长度小于等于nums2if n1 > n2:nums1, nums2 = nums2, nums1n1, n2 = len(nums1), len(nums2)​idx1 = n1-1idx2 = N_left - (idx1+1)# 注意这里idx2的最大取值为n2-1,原因在于限制了n1 <= n2while nums1[idx1] > nums2[idx2] and idx1 > -1 and idx2 < n2-1:idx1 -= 1idx2 += 1if odd:    # odd为True时有两种情况:nums1的数全分配到左边或左右都有# (由于odd为True时必有n1<n2,因此nums2的数不可能全部分配到左边)if idx1 == n1-1: # nums1的数全分配到左边mid = nums2[idx2]else:mid = min(nums1[idx1+1], nums2[idx2])else:# odd为False时计算左边部分最大值,有三种情况if idx1 == -1: # nums1的数全部分配到右边max_left = nums2[idx2-1]elif idx2 == 0: # nums2的数全部分配到右边max_left = nums1[idx1]else:max_left = max(nums1[idx1], nums2[idx2-1])# odd为False时计算右边最小值,有两种情况# (由于N为偶数且n1 <= n2,因此当nums2的数全部分配到左边时,实际上n1 == n2,#  计算中位数时也要取nums2最后一个值)if idx1 == n1-1: # nums1的数全分配到左边min_right = nums2[idx2]else:min_right = min(nums1[idx1+1], nums2[idx2])​mid = (max_left + min_right) / 2return mid
​
​
if __name__ == '__main__':    nums1 = [1, 3, 5, 7, 9]nums2 = [2, 4, 6, 8, 10, 11]print(Find2OrderedListMid(nums1, nums2))

欢迎关注公众号:一本正经d胡说
Genlovy562

这篇关于算法/编程练习:两个有序数组的中位数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1136698

相关文章

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

Java中数组转换为列表的两种实现方式(超简单)

《Java中数组转换为列表的两种实现方式(超简单)》本文介绍了在Java中将数组转换为列表的两种常见方法使用Arrays.asList和Java8的StreamAPI,Arrays.asList方法简... 目录1. 使用Java Collections框架(Arrays.asList)1.1 示例代码1.

java两个List的交集,并集方式

《java两个List的交集,并集方式》文章主要介绍了Java中两个List的交集和并集的处理方法,推荐使用Apache的CollectionUtils工具类,因为它简单且不会改变原有集合,同时,文章... 目录Java两个List的交集,并集方法一方法二方法三总结java两个List的交集,并集方法一

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为

C++一个数组赋值给另一个数组方式

《C++一个数组赋值给另一个数组方式》文章介绍了三种在C++中将一个数组赋值给另一个数组的方法:使用循环逐个元素赋值、使用标准库函数std::copy或std::memcpy以及使用标准库容器,每种方... 目录C++一个数组赋值给另一个数组循环遍历赋值使用标准库中的函数 std::copy 或 std::