最初的想法是对于L1和L2,长度各为len1,len2,各取他们的中位数m1,m2(因为L1和L2已经排序)(假设这里L1[m1]>L2[m2]),除开L1最大值小于L2的最小值这种特殊情况,则待求中位数一定位于L1[m1]与L2[m2]之间,然后再取L1[0,m1],L2[len2-m2,len2]这两段重复上面的操作。但是很明显这种想法是错误的,可以假设中值m位于L1[m1,len1-1]之间,那么只要在L2[m2,len2-1]之间存在多于(len1+len2)/2个大于m的数,这个假设就可以成立。
正确的思路是通过考虑到两个list之间的限制关系:很明显,这个问题最终会将两个list分别分为左右两堆,左边任意一堆小于右边任意一堆,而且左右两边的数字个数相同,我们可以假设左边是L1[0,,,i-1],L2[0,,,j-1],右边是L1[i,,,len1-1],L2[j,,,len2-1],很明显若len1+len2为偶数,则i+j-2 = len1-i+len2-j,但是考虑到奇数,我们可以处理为j=(len1+len2+1)/2,此时若长度之和为奇数,则左边堆比右边堆多一个。然后就是L1[i-1]<=L2[j],L2[j-1]<=L1[i]。然后就可以在L1中进行二叉树遍历。找到左边堆中最大的于右边堆中最小的,然后若长度和为奇数,返回左边堆最大的,否则返回左边堆最大的与右边堆最小的平均数。
基本思路是这样,但是考虑到i-1,i,j-1,j可能不存在的情况:也就是i<0,i>=len1这样的情况,就需要进行特殊处理:i<0意味着L1的最小值都比L2的最大值大,明显左边堆的最大值直接就取L2[j-1],因为左边堆中不会有L1的数字,同理若j<0左边堆的最大值直接就取L1[1-1];而i>=len1意味着L1的最大值都比L2的最小值小,右边堆的最小值直接就取L2[j],j>=len2类推。
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
l1 = len(nums1)
l2 = len(nums2)
if l2 > l1:
temp_nums1 = nums1
temp_nums2 = nums2
else:
temp_nums1 = nums2
temp_nums2 = nums1
l1 = len(temp_nums1)
l2 = len(temp_nums2)
iMin = 0
iMax = l1
while True:
i = (iMin+iMax) // 2
j = (l1+l2+1) // 2 - i
if i > iMin and temp_nums1[i-1] > temp_nums2[j]:
iMax -= 1
elif i < iMax and temp_nums2[j-1] > temp_nums1[i]:
iMin += 1
else:
break
if i == 0:
maxLeft = temp_nums2[j-1]
elif j == 0:
maxLeft = temp_nums1[i-1]
else:
maxLeft = max(temp_nums1[i-1], temp_nums2[j-1])
if (l1+l2)%2 == 1:
return maxLeft
if i == l1:
minRight = temp_nums2[j]
elif j == l2:
minRight = temp_nums1[i]
else:
minRight = min(temp_nums1[i], temp_nums2[j])
if (l1+l2)%2 == 0:
return (maxLeft+minRight) / 2
,
博客先指出最初求解两个有序列表中位数的错误思路,即取两列表中位数再缩小范围操作。接着给出正确思路,将两列表分别分为左右两堆,满足左堆小于右堆且数量关系特定,通过二叉树遍历求解,还提及对索引越界情况的特殊处理。
548

被折叠的 条评论
为什么被折叠?



