我有两套 -
set1 - {i1,i2,i3 ... iN1}
set2 - {k1,k2,k3 ... kN2}
对于n个项目的任何一组,我可以使用位掩码0-2 ^ n -1表示所有可能的子集。 同样,我怎么能代表 -
set1和set2的所有可能子集,其中至少有1个项目来自不同的集合。
例如,{i1,i2,k1}有效
但{i1,i2} - 无效,因为它没有来自set2的项目。
我正在尝试生成两件事 -
一种方程式,它可以给我一个所有子集的计数,就像我们有一个n项子集的2 ^ n个子集。
比特编码/掩码用于表示上述类型的子集。
答案 0 :(得分:0)
如果我们引入一些额外的兴趣,这将更容易。让我们调用两个输入集S1和S2;我们定义集L,C和R(左,中,右)。将这些视为维恩图。因此,定义L = S1 \ S2,S1中的元素根本不在S2中; C =S1∩S2,S1和S2中的元素,R = S2 \ S1。我们还分别为这些集的大小写l,c和r。
现在我们准备好回答问题1:S1∪S2的子集有多少来自S1并且有一个来自S2的元素?有两种情况需要考虑:要么我们有一个带有C元素的子集(它满足"来自S1和#34的元素;"来自S2"元素的元素),或者我们在C中没有元素,L和R中至少有一个元素。在第一种情况下,有(2 ^ c - 1)个非空C子集,其余为2 ^(l + r)个子集,所以在那种情况下有(2 ^ c - 1)* 2 ^(l + r)组。在第二种情况下,有2 ^ l - 1个非空子集L和2 ^ r - 1个非空子集R,所以有(2 ^ l - 1)*(2 ^ r - 1)个子集在这种情况下。加上这两种情况,我们总共有满足条件的2 ^(c + l + r) - 2 ^ l - 2 ^ r个子集。
如果您有非空子集的奇特表示,这也会立即建议用于存储这些子集的数据结构:您所处的情况的单个位标记,以及子集和非空的适当表示每种情况下的子集。
但我可能只使用一个大小为c + l + r的位掩码,即使有一些"无效" bitmasks:它非常紧凑,检查有效性很容易,并且在位掩码上有许多便宜的操作。