有两个分别为大小为m和n的排序数组A和B.找到两个排序数组的中位数。总运行时间复杂度应为O(log(m + n))。
我不明白计算aMid和bMid的公式。这些公式背后的逻辑是什么?
int aMid = aLen * k /(aLen + bLen); //一个中间计数
int bMid = k - aMid - 1; // b的中间计数
这是程序的链接。 http://www.programcreek.com/2012/12/leetcode-median-of-two-sorted-arrays-java/][1]
public static double findMedianSortedArrays(int A[], int B[]) {
int m = A.length;
int n = B.length;
if ((m + n) % 2 != 0) // odd
return (double) findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1);
else { // even
return (findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1)
+ findKth(A, B, (m + n) / 2 - 1, 0, m - 1, 0, n - 1)) * 0.5;
}
}
public static int findKth(int A[], int B[], int k,
int aStart, int aEnd, int bStart, int bEnd) {
int aLen = aEnd - aStart + 1;
int bLen = bEnd - bStart + 1;
// Handle special cases
if (aLen == 0)
return B[bStart + k];
if (bLen == 0)
return A[aStart + k];
if (k == 0)
return A[aStart] < B[bStart] ? A[aStart] : B[bStart];
int aMid = aLen * k / (aLen + bLen); // a's middle count
// I AM STUCK HERE
int bMid = k - aMid - 1; // b's middle count
// make aMid and bMid to be array index
aMid = aMid + aStart;
bMid = bMid + bStart;
if (A[aMid] > B[bMid]) {
k = k - (bMid - bStart + 1);
aEnd = aMid;
bStart = bMid + 1;
} else {
k = k - (aMid - aStart + 1);
bEnd = bMid;
aStart = aMid + 1;
}
return findKth(A, B, k, aStart, aEnd, bStart, bEnd);
}
我从代码的评论中得到了一些想法,如何计算这些公式,但仍然不明白向某人解释“为什么这些公式”或这些公式背后的逻辑是什么?
对于int aMid = aLen * k /(aLen + bLen); //一个中间数 作为aMid = aLen / 2 - (i)
和k =(aLen + bLen)/ 2, - &gt; 2 =(aLen + bLen)/ k
将值2放在equ(i)
中所以aMid = aLen /(aLen + bLen)/ k == aLen * k /(aLen + bLen)
和int bMid = k - aMid - 1; // b的中间计数
aMid + bMid + 1 = k必须满足才能在A [aMid]&gt;时得出结论。 B [bMid]
至于为什么aMid + bMid + 1 = k是重要的:如果A [aMid]大于B [bMid],你知道A中A [aMid]之后的任何元素都不能是第k个元素B中有太多元素低于它(并且会超过k个元素)。你也知道B [bMid]和B中B [bMid]之前的任何元素都不能是第k个元素,因为A中的元素太少而不是它(在B [bMid]之前没有足够的元素)是第k个元素。)
答案 0 :(得分:2)
正如您已经提到的那样:aMid + bMid + 1 = k
必须满足才能得出以下结论:
A[aMid] > B[bMid]
bMid
我们可以在aMid
之前扔掉所有内容,在bMid
之后扔掉所有内容,
因为我们知道有aMid
+ 1
+ aMid
(包括= k
)A[aMid]
元素小于aMid
。因此,我们的中位数在于其余阵列
考虑到这一点,我们首先设置两个中间值bMid
和IndexOutOfBoundsException
并不重要。唯一要注意的是不要让其中一个引起int aMid = 0;
int bMid = k - aMid - 1;
if(bMid >= bLen) {
bMid = bLen - 1;
aMid = k - bMid - 1;
}
。
O(log(n+m))
也可以做到这一点。但这需要花费A[0]
次,因为在最坏的情况下,我们只会跳过一个元素(aLen + bLen
)。
我们想要的是总是扔掉A > B
的百分比
在我们的例子中,这是:
A&gt; B:k = k - (bMid +1)= k - (k - aMid)= aMid = k *(aLen /(aLen + bLen))
B> A:k = k - (aMid + 1)= k - (k * aLen /(aLen + bLen))-1 = k *(bLen /(aLen + bLen)) - 1
忽略-1并假设B > A
的概率与E(k) = 0.5 * k * (aLen/(aLen + bLen)) + 0.5 * k * (bLen/(aLen + bLen))
相同,我们得到:
= 0.5 * k (aLen + bLen)/(aLen + bLen) = 0.5 * k
O(log(n + m))
这意味着我们得到大约k
递归调用,直到app.use(express.static(path.join(__dirname, "public")));
app.use(logger('dev'));
app.use(bodyParser.json({limit: '50mb'}));
app.all('/*', function(req, res, next){
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS");
res.header("Access-Control-Allow-Headers", "Content-type,Accept,X-Access-Token,X-Key");
if(req.method === 'OPTIONS'){
res.status(200).end();
} else {
next();
}
});
app.all("/api/v1/*", [require('./middlewares/validateRequest')]);
app.use("/", require("./routes"));
app.use(function(req, res, next){
var err = new Error("Not found");
err.status = 404;
next(err);
});
为0,然后函数停止。