假设我有两个数据库,每个数据库包含n
条目。将中位数定义为n
&#39最小值。我们可以通过查询从给定的数据库中一次提取一个值。
Query(k)
返回k
指定数据库的最小值。如何使用最多O(log n)
次查询找到中位数?
答案 0 :(得分:2)
所需的时间复杂度为n
,表明我们应该尝试找到二元搜索方法。与二分搜索类似但略有不同,我们仍然每次将// As Query(k) will return k'th smallest element, considering database as container of sorted entries for understanding purpose.
E.g., DB1 = [1, 3, 5, 7, 9] DB2 = [2, 4, 6, 8, 10]. n = 5.
i = n / 2 = 2;
j = n - i = 3;
i
DB1 [1, 3, 5, 7, 9]
j
DB2[2, 4, 6, 8, 10]
分成两半。
DB1.Query(i) < DB2.Query(j)
如果1
,则表示i
至DB1
中包含n
的元素必须存在于第一个(n - i)
元素中。
现在,下一步是找到n / 2
中的DB1
(等于i + 1
)元素(从n
到DB2
)和{{ 1}}(从1
到n
)。这个程序可以被视为&#34;切割&#34;来自一个数据库的n / 2
个元素,并继续从另一个数据库和&#34; new&#34;中找到其他n / 2
个元素。切割后的数据库。
如果DB1.Query(i) > DB2.Query(j)
,则应用相同的程序,但我们会切断&#34; DB2
数据库。
通过这种方式,我们每次都有&#34; cut&#34;来自其中一个数据库的n / 2
个元素,下一次是从该数据库中删除(n / 2) / 2
个元素,直到:
n = 1
,DB1.Query(1)
和DB2.Query(1)
中较小的一个是&#34; nth元素&#34;。n
元素。我假设DB1
和DB2
是两个数据库的数据库处理程序。这种语法类似于C ++,但你可以理解。这可确保O(log n)
复杂性。
// Find k'th smallest element of the two combind database entries
int findMedianofDatabaseHelper(DBHandler* db1, int i, DBHandler* db2, int j, const int n, int k) {
if((n - i) > (n - j))
{
return findMedianofDatabaseHelper(db2, j, db1, i, n, k);
}
if(i >= n)
{
return db2->Query(j + k);
}
if(j >= n)
{
return db1->Query(i + k);
}
if(k == 1)
{
return min(db1->Query(i + 1), db2->Query(j + 1));
}
int aMid = min(k / 2, n - i);
int bMid = k - aMid;
if(db1->Query(i + aMid) <= db2->Query(j + bMid))
{
return findMedianofDatabaseHelper(db1, i + aMid, db2, j, n, k - aMid);
}
return findMedianofDatabaseHelper(db1, i, db2, j + bMid, n, k - bMid);
}
// assuming DBHandler is a wrapper of database handler/instance on which we can perform query
int findMedianofDatabase(DBHandler* db1, DBHandler* db2, int n)
{
return findMedianofDatabaseHelper(db1, 0, db2, 0, n, n);
}
Here我用C ++模拟了工作程序。
答案 1 :(得分:0)
你基本上可以通过二分搜索找到它(如果n不是2的幂,则可以进行一些调整):查询两个数据库中的n/2
- 最小元素m1, m2
。如果他们是平等的,那么你有中位数。如果是m1<m2
,则要求3n/4
- 第一个最小,1/4
- 第二个最小,反之亦然m1>m2
。重复。
在每个步骤中,您所选元素的元素数量与上面相同。