如何使用C#从整数数组构建可能性树?如果在每一步中从数组中删除一个元素,我需要制作所有可能的数组变体。
例如,如果我们有三个整数的数组[1,2,3],那么树应该是这样的:tree view
答案 0 :(得分:1)
我会将其视为二进制算术问题:
static void Main(string[] args)
{
int[] arr = { 1, 2, 3 };
PickElements(0, arr);
}
static void PickElements<T>(int depth, T[] arr, int mask = -1)
{
int bits = Math.Min(32, arr.Length);
// keep just the bits from mask that are represented in arr
mask &= ~(-1 << bits);
if (mask == 0) return;
// UI: write the options
for (int i = 0; i < depth; i++ )
Console.Write('>'); // indent to depth
for (int i = 0; i < arr.Length; i++)
{
if ((mask & (1 << i)) != 0)
{
Console.Write(' ');
Console.Write(arr[i]);
}
}
Console.WriteLine();
// recurse, taking away one bit (naive and basic bit sweep)
for (int i = 0; i < bits; i++)
{
// try and subtract each bit separately; if it
// is different, recurse
var childMask = mask & ~(1 << i);
if (childMask != mask) PickElements(depth + 1, arr, childMask);
}
}
对于TreeView
,只需用节点创建替换Console.Write
等,可能会将父节点作为递归的一部分传入(和向下)(代替depth
,也许)。
要了解这是做什么的,请考虑二进制文件; -1是:
11111111111111...111111111111111
然后我们查看bits
,我们从数组长度得出,并在此示例中找到3。我们只需要看3位,然后;这一行:
~(-1 << bits)
为此计算一个掩码,因为:
-1 = 1111111....1111111111111
(-1 << 3) = 1111111....1111111111000 (left-shift back-fills with 0)
~(-1 << 3) = 0000000....0000000000111 (binary inverse)
然后我们将其应用于输入掩码,因此我们只能通过mask &= ...
查看最不重要的3位。如果结果为零,我们已经没有事情可做,所以请停止递归。
UI更新很简单;我们只扫描我们关心的3位,检查当前位是否为&#34; on&#34;为我们的面具; 1 << i
创建一个只有&#34; i-set bit&#34;的掩码; &
和!= 0
检查该位是否已设置。如果是,我们在输出中包含元素。
最后,我们需要启动取走位,查看子树;我们可能可能对此更为复杂,但我选择只扫描所有位并尝试它们 - 最坏的情况是这是每级32位测试,这没什么。和以前一样,1 << i
创建了一个只有&#34; i-set bit&#34;的掩码。这次我们要禁用那个位,所以我们&#34;否定&#34;和&#34;和&#34;通过mask & ~(...)
。这个位可能已经禁用,因此childMask != mask
检查确保我们只有实际递归时我们禁用了之前启用的位。
最终结果是我们最终连续使用了掩码:
11..1111111111111111 (special case for first call; all set)
110 (first bit disabled)
100 (first and second bits disabled)
010 (first and third bits disabled)
101 (second bit disabled)
100 (second and first bits disabled)
001 (second and third bits disabled)
011 (third bit disabled)
010 (third and first bits disabled)
001 (third and second bits disabled)
请注意,对于更简单的组合示例,可以只在单个for
中进行迭代,使用位来拾取元素;但是,我已经用递归的方式完成了它,因为我们需要构建一个连续减法的树,而不是没有特定顺序的平坦可能性。