找到每个可能子集的第k个最小和

时间:2015-10-19 16:46:02

标签: algorithm sorting subset


上次我发现有趣的问题,我被卡住了。

给定n个数a [1],...,a [n]按升序排列,数字k(1 <= n,k <= 10 ^ 5)。

假设我们用和来对给定序列的每个可能子集进行排序。
我们必须找到第k个这样子集的总和。

例如:
n = 4,k = 8
a = {2,7,8,15}

1:{2},sum = 2
2:{7},sum = 7
3:{8},sum = 8
4:{2,7},sum = 9
5:{2,8},sum = 10
6:{7,8},sum = 15
7:{15},总和= 15
8:{2,15},sum = 17
...
k = 8,所以答案= 17(子集{2,15})。

当然我们可以生成每个可能的子集,整个解决方案在O(2 ^ n * n)中运行,但我正在寻找更智能的东西 - 线性,或至少O(nk)。

1 个答案:

答案 0 :(得分:9)

(为简单起见假设非空子集。处理空子集是一行或两行。)

给定索引的非空子集S,将S定义为S \ {max(S)} U {max(S) + 1}S U {max(S) + 1}。从{1}开始,子关系形成一个树,其中包含每个非整数的正整数子集。

{1}
|  \
{2} {1,2}______
|  \     \     \
{3} {2,3} {1,3} {1,2,3}

以相应数组元素的总和为关键字,此树是一个最小堆。如果你仔细计算密钥(通过添加和减去而不是从头开始求和)并懒惰地实现最小堆删除,那么你得到一个O(k log k)时间算法。