示例 1:
nums1 = [1, 3] nums2 = [2] 中位数是 2.0
示例 2:
nums1 = [1, 2] nums2 = [3, 4] 中位数是 (2 + 3)/2 = 2.5
解题思路:
糟糕- -没理解题意,首先需要知道“中位数”的含义,其次,题目对时间复杂度做了要求,必须为O(log (m+n))。
先写理解的代码,猜测题意:
nums = sorted(nums1 + nums2)
lenth = len(nums)
if lenth % 2 == 0:
return (nums[lenth//2] + nums[lenth//2 - 1]) / 2
else:
return nums[lenth//2]
116 ms,打败了47.53%的对手。
[沉思],也就是说,我对题目的理解是正确的,本题确实要输出两个排序数组最中间的数。
本题的难点在于排序算法,
我用Python自带sorted排序算法就不对了,我需要找到尽可能快的排序算法并写出。
解题思路1:
排序有多种方式,在网上可以轻易搜到。
但本题的重点,是排序两个有序数组。
我想,用一个数组挨个往另一个数组里插是个不错的选择。
如图:
..............画的什么鬼图.................
代码:
nums = nums1 + nums2
for i in range(len(nums1), len(nums)):
for j in range(i, -1, -1):
if nums[i] < nums[j]:
nums[i], nums[j] = nums[j], nums[i]
i = j
# print(nums)
lenth = len(nums)
if lenth % 2 == 0:
return (nums[lenth // 2] + nums[lenth // 2 - 1]) / 2
else:
return nums[lenth // 2]
然则............Time Limit Exceeded............
也对....sorted排序是底层语言写的...我这排序又怎么能快过它.............
所以,要么有更快速的排序,要么,这道题真正的做法不是排序。
解题思路2:
仔细思考一下,这道题并不需要生成排序的数组- -只是要找到中位数罢了。
lenth = len(nums1) + len(nums2)
loc = lenth // 2 - 1
print(loc)
i, j, count = 0, 0, 0
while i < len(nums2) and j < len(nums1) and count != loc:
if nums2[i] > nums1[j]:
j = j + 1
else:
i = i + 1
count = j + i
if i == len(nums2):
median = nums1[lenth // 2 - i]
if lenth % 2 == 0:
prevMedian = nums1[lenth // 2 - i - 1]
elif j == len(nums1):
median = nums2[lenth // 2 - j]
if lenth % 2 == 0:
prevMedian = nums2[lenth // 2 - j - 1]
elif count == loc:
if nums2[i] > nums1[j]:
prevMedian = nums1[j]
j = j + 1
else:
prevMedian = nums2[i]
i = i + 1
if i == len(nums2):
median = nums1[lenth // 2 - i]
elif j == len(nums1):
median = nums2[lenth // 2 - j]
elif nums2[i] > nums1[j]:
median = nums1[j]
j = j + 1
else:
median = nums2[i]
i = i + 1
# print(i, j, prevMedian, median)
if lenth % 2 == 0:
return ((prevMedian + median) / 2)
else:
return median
148 ms,打败了31.36%的对手。
更重要的是- -我写的真恶心........
如果说这个算法有什么缺点的话,那应该是从中间比较而不是从最初比较。
来看一下官方解题思路..
解题思路3:
这道题官方甚至给了Python代码。
而且- -没有用模除,修改后的代码如下:
m, n = len(nums1), len(nums2)
if m > n:
nums1, nums2, m, n = nums2, nums1, n, m
if n == 0:
raise ValueError
imin, imax, half_len = 0, m, (m + n + 1) // 2
while imin <= imax:
i = (imin + imax) // 2
j = half_len - i
if i < m and nums2[j-1] > nums1[i]:
# i is too small, must increase it
imin = i + 1
elif i > 0 and nums1[i-1] > nums2[j]:
# i is too big, must decrease it
imax = i - 1
else:
# i is perfect
if i == 0: max_of_left = nums2[j-1]
elif j == 0: max_of_left = nums1[i-1]
else: max_of_left = max(nums1[i-1], nums2[j-1])
if (m + n) % 2 == 1:
return max_of_left
if i == m: min_of_right = nums2[j]
elif j == n: min_of_right = nums1[i]
else: min_of_right = min(nums1[i], nums2[j])
return (max_of_left + min_of_right) / 2.0
144ms,打败了35.78%的对手。
很好,这个故事告诉我们,请消停的排序,不要满脑子骚操作。
这个算法与我的找中位数的算法不同为:
.........就是完全一样,只是我是从最小开始比,这个算法是从中间开始比。下次我注意。
解题思路4:
来看一下讨论区,有没有哪位前辈分享代码。
...............................没找到更好的算法.........................莫非是我英语水平不够?
前面的53%的用户到底是怎么做的?
待我查查其他博客文章。
这篇文章使用了nums.append(nums1.pop(0))的方法来排序,只花了112ms。
我终于学到了如何查看更快的算法,原来是直接点击柱状图就可以。