1、题目
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。 你可以假设 nums1 和 nums2 不会同时为空。
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
2、分析
是将两个已经排序的列表进行合并,并找到中位数,但是题目要求了时间复杂度,所以需要在合并时排序方面进行选择,log首先会想到二分法,这样的话不会对全部的数据进行查找,这样时间复杂度会比较小,但是我在这里根据问题使用了类似二分法的改进版。每次去判断最后一位是否是一个小值,然后将之后的数全部合并,这样的话会节省大量的判断的时间,当然这里也可以使用sorted函数,这是我一开始没有想到的,最后发现使用sorted函数得分却是非常的高。
3、代码
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
x, y = 0, 0
l = len(nums1)
if (len(nums1) == 0 ) or (len(nums2) == 0):
if len(nums1) == 0:
return (nums2[int( len(nums2)/2 )] + nums2[ int( len(nums2)/2 - 1) ]) / 2 if len(nums2) & 1 == 0 else nums2[int( len(nums2)/2 - 0.5) ]
if len(nums2) == 0:
return (nums1[int( len(nums1)/2 )] + nums1[ int( len(nums1)/2 - 1) ]) / 2 if len(nums1) & 1 == 0 else nums1[int( len(nums1)/2 - 0.5) ]
while True:
# 全部插入到 nums1
if nums1[x] > nums2[y]:
nums1.insert(x, nums2[y])
y += 1
if x+1 == len(nums1):
x = x
else:
x = x+1
if len(nums1) == l + len(nums2): # **
break
# 这里代码的实现感觉是非常重要的,每次去判断最后一位是否是最小值
# 然后将未插入的元素全部插入到这个值的后面
# 极大的减少了判断元素的时间
if nums1[-1] <= nums2[y]:
nums1 = nums1 + nums2[y:]
return (nums1[int( len(nums1)/2 )] + nums1[ int( len(nums1)/2 - 1) ]) / 2 if len(nums1) & 1 == 0 else nums1[int( len(nums1)/2 - 0.5) ]
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
# 这里只是用三行代码就实现了要求
# sorted使用的是 timsort是一个稳定的排序函数,时间复杂度为 nlog(n)
nums1 = nums1 + nums2
nums1 = sorted(nums1)
return (nums1[int( len(nums1)/2 )] + nums1[ int( len(nums1)/2 - 1) ]) / 2 if len(nums1) & 1 == 0 else nums1[int( len(nums1)/2 - 0.5) ]
4、结果
# 第一种方法
执行用时 :108 ms, 在所有 python3 提交中击败了88.50% 的用户
内存消耗 :12.9 MB, 在所有 python3 提交中击败了99.43%的用户
# 第二种方法
执行用时 :104 ms, 在所有 python3 提交中击败了94.16% 的用户
内存消耗 :12.9 MB, 在所有 python3 提交中击败了99.43%的用户
5、改进
第一种感觉在判断一方为空时占用的时间比较多,没有将这一步的计算与大众的数据集成在一起,应该将if判断的代码优化一下,可能时间复杂度会更小,当然执行的用时也是根据随机数据随机计算的,不过在数据量小的情况下应该会比二分法速度要快。
望您:
“情深不寿,强极则辱,谦谦君子,温润如玉”。