Median of Two Sorted Arrays
这个题太难了,看到方法之后都不会编的那种,各种复杂,各种边界条件。
首先,要把这个问题转化为求两个有序数组中第K个数的问题;
求第K个数问题,关键是2分的时候把谁删除掉,网上的解法多少都有些晦涩难懂,这里面有一个“至多”,“至少”的问题,完整python代码如下,代码后面有解释:
class Solution:
# @return a float
def findMedianSortedArrays(self, A, B):
m = len(A)
n = len(B)
if m == 0 and n == 0:
return 0
k = m + n
if k % 2 == 0:
return (self.find_kth(A, B, k/2) + float(self.find_kth(A, B, k/2+1)))/2
else:
return self.find_kth(A, B, k/2+1)
def find_kth(self, A, B, k):
m = len(A)
n = len(B)
if m == 0:
return B[k-1]
if n == 0:
return A[k-1]
i = m / 2
j = n / 2
if A[i] <= B[j]:
p = A
q = B
else:
p = B
q = A
i, j = j, i
t = i + j + 1
if k <= t:
return self.find_kth(p, q[:j], k)
else:
return self.find_kth(p[i+1:], q, k - i - 1)
首先第一个函数很简单,调用找第k大的;主要看第二个函数,怎么找的第k大;
find_kth(self, A, B, k)
举个栗子:
A:[3, 5, 9, 10, 12, 15]
B:[1, 7, 10, 11, 15, 19, 22]
k:5
比较两个的中值,A[3]=10 和 B[3]=11, 发现A[3]<=B[3](如果发现A的中值>B的中值那么就调换A,B位置,主要是为了方便,也可以分开写),这个说明什么呢,非常关键,解决这个问题的核心所在:
说明了,B[3]前面至少有(3+3+1)=7个元素,B[3]至少是第(3+3+1)+1=8大,要么是并列(即便B[3]身处并列,即便是并列第一,那他前面也可以认为有7个),要么是第8,9,10,11...(因为A[3]右侧的也可能小于B[3]);
还说明了,A[3]至多是第(3+3+1)大,道理和上面一样,如果B[3]前面的也都小于A[3]那么,A[3]最大,是第七名;
为啥呢?怎么就说明了呢?
A[3] < =B[3], 那么:
(1)A[0-3]以及B[0-2]都是<=B[3],那么怎么着B[3]前面也会有7个元素,
(2)A[3]<=B[3],B[3]前面最多有7个元素,A[3]如果是紧挨着B[3]的,那么他也就是第7大,他不可能比A[4]之后的大
这样我们就有这么个知识了,A[3]至多第7大,B[3]至少第8大,然后去看K
因为k = 5:
k <= 7,那么就说明,B[3]往后,连同B[3]都可以删除掉,肯定不是我们找的,我们找第5名的,那我们知道了B[3]至少第8,所以把B中B[3]往后(含B[3])的全部干死;
那如果k = 8呢:
k >7,那么就说明,A[3]往前,连同A[3]全部都可以删除到,肯定不是我们找的,我们找第8名,我们知道A[3]最多也就是第7,所以把A[3]之前(含A[3])全部干死;
然后进入递归;
A:[3, 5, 9, 10, 12, 15]
B:[1, 7, 10]
k:5
以此类推
需要注意的是,如果删掉的是A的前半部分,那么K的值也要相应更改,因为你想要找第9,删掉了3个最小的,在剩下的集合中,你就不是找第9了,而是找第6了;
还有就是递归结束条件是有一个数组长度为0了