介绍discussion里面的不是findkth的算法,也当学习了
这个算法是MissMary在leetcode的discussion里面讲述的,我在这儿翻译一下,也算学习了一下。
正文
中位数是用来干什么的?主要是用来把一个集合分成长度相等的两部分,其中左面的部分肯定要比面的部分小。
把集合A随机分成两部分
| A[0], A[1], ... ,A[i+1] | A[i], A[i+2], ..., A[m] | leftA | rightA |
分割的方法有m+1种, 如果len(leftA) = i, len(rightA) = m - i,当 i = 0, leftA为空,当i = m, rightA为空。
同样可以把集合B分成两部分
| B[0], B[1], ... ,B[j-1] | B[j], B[j+2], ..., B[n] | leftB | rightB |
合并它俩
| B[0], B[1], ... ,B[j-1] | B[j], B[j+2], ..., B[n] | A[0], A[1], ... ,A[i-1] | A[i], A[i+2], ..., A[m] | leftpart | rightpart
如果我们能够保证
- len(leftpart) == len(rightpart)
- max(leftpart) <= min(rightpart)
那么我们就能计算出中位数median是
(max(leftpart) + min(rightpart)) / 2
下面是整个逻辑最清楚的地方,如果要保证这两个条件,那么我们必须保证下面的条件
- i + j == m - i + n - j(或者 m-i+n-j+1)
如果n>=m,可以设i = 0~m, j = (m+n-1)/2-i- A[i-1] <= B[j] and B[j-1] <= A[i]
所以就改成了如下的方式:
Searching i in [0, m], to find an object
i
that:
B[j-1] <= A[i] and A[i-1] <= B[j], ( where j = (m + n + 1)/2 - i )
而查找的方法就可以用二分查找法了
Set imin = 0, imax = m, then start searching in [imin, imax]
Set i = (imin + imax)/2, j = (m + n + 1)/2 - i
现在 len(left_part)==len(right_part). 会有三种情况如下
3.1. B[j-1] <= A[i] and A[i-1] <= B[j]
如果满足上面的条件,就是找到了满足复合要求的
3.2. B[j-1] > A[i]
说明A[i]太小了,我们必须调整i使得它B[j-1] <= A[i]
.
我们可以增加 i 吗?
是的,因为如果增加i,j也会被增加所以 B[j-1] 被减少 and A[i] 被增加, and
B[j-1] <= A[i]
可能会满足
我们可以减少 i 吗?
显然不能,因为当我们减少i的时候,j 会被增加.
所以B[j-1]被增加,and A[j]被减少,andB[j-1] <= A[i]会永远不会被满足
所以我们必须增加i,然后调整范围[i+1, imax]. 即 imin = i+1, and 去第二步.
3.3. A[i-1] > B[j]
means A[i-1]太大,并且我们必须减少i使得可以满足
A[i-1]<=B[j].
然后调整范围这样: [imin, i-1].
即 imax = i-1, and 去第二步.