我不确定我需要的是否有名字,但它非常接近电源。这就是欲望:
Input:[1,2,3,4]
Output:
[1,2,3,4]
[1,2,3]
[1,2,4]
[1,3,4]
[1,2]
[1,3]
[1,4]
这与3种方式的电源设置不同:
1
)我目前的解决方案是创建一个电源设置,过滤掉不以第一个值开始的值,然后反向排序。这太慢了,所以我正在寻找更好的解决方案。
从最长到最短,我在每个子集上运行测试,直到找到一个返回true的集合。这让我想知道我是否可以使用发电机,所以我不必一次创建所有值(很高兴有,但不是必需的,因为最大尺寸只有~25个成员,或~33MM套)。
任何帮助表示赞赏!
答案 0 :(得分:0)
使用位掩码可以轻松生成功率集。
考虑集合A = {1, 2, 3, 4}
。定义一个4元素布尔向量并将其表示为I
。现在,定义B = { A[i] | I[i] = true }
。有两件事需要注意:
B
显然是A
的一个子集。I
的可能值,我们可以生成所有子集I
,将每个位视为一个布尔值。话虽这么说,这是一个生成数组所有子集的算法:
"use strict";
var input = [1, 2, 3, 4];
var isMemberInSet = function (indexingVector, _, index) {
return indexingVector & (1 << index);
}
var subsetCount = Math.pow(2, input.length);
for (var indexingVector = 0; indexingVector < subsetCount; indexingVector++) {
var subset = input.filter(isMemberInSet.bind(undefined, indexingVector));
console.log(subset);
}
但我们可以做得更好!事实上,对上述算法的一些简单修改可以完全解决您的问题。
首先,由于我们需要始终包含数组的第一个值,因此我们需要镜像索引向量生成。换句话说,重新定义B = { A[I.length - i - 1] | I[i] = true }
。
其次,我们需要以相反的顺序迭代索引向量,这意味着:
for (var i = subsetCount - 1; i >= 0; i--)
第三,因为我们不关心所有子集,而只关注那些长度> gt的子集。 2我们不需要一直迭代到0,而只是迭代到pow(2, input.length - 1)
,因为这是仅包含第一个和第二个值的索引向量,而索引向量的所有其他值都不包括第一个值:
var subsetsContainingTheFirstValue = Math.pow(2, input.length - 1);
for (var i = subsetCount - 1; i > subsetsContainingTheFirstValue; i--)
最后,我们得到了这段代码:
"use strict";
var input = [1, 2, 3, 4];
var integerSize = 32;
var isMemberInSet = function (indexingVector , _, index) {
return indexingVector & (1 << (input.length - index - 1));
}
var subsetCount = Math.pow(2, input.length);
var subsetsContainingTheFirstValue = Math.pow(2, input.length - 1);
for (var indexingVector = subsetCount - 1; indexingVector > subsetsContainingTheFirstValue; indexingVector --) {
var subset = input.filter(isMemberInSet.bind(undefined, indexingVector ));
console.log(subset);
}
输出:
[1, 2, 3, 4]
[1, 2, 3]
[1, 2, 4]
[1, 2]
[1, 3, 4]
[1, 3]
[1, 4]
注意:上面的代码是有效的,因为你提到最大元素数是25.如果这个数字超过32,我们将无法使用整数而且需要布尔数组。