给定一个数组:
$array = array(1,2,3);
如何创建包含所有可能子集的数组:
[1, 2, 3, [1,2], [1,3],[2,3]]
答案 0 :(得分:0)
我认为这是一个很好的问题 - 查找集合的子集有几种方法 我更喜欢使用二进制方法:
给定的一组n^2
有n
个susets。您可以从0到2 ^ n计算二进制数,并将二进制数解释为相应的子集。请注意,此方法需要具有足够数字位数的二进制数来表示整个集合,因此我们需要填充二进制表示。
更多阅读:binary-subsets
我的实施:
$arr = array(1,2,3);
$res = subsets($arr);
function subsets($arr,$sort = true,$include_empty = false,$include_full = false) {
$length = count($arr);
$res = array();
if (!$length && $include_full) return $res;
for ($i = 0; $i<pow(2, $length); $i++) {
$set = array();
$bin = str_split(str_pad(decbin($i), $length, "0", STR_PAD_LEFT));
$binLen = count($bin);
for ($j = 0; $j < $binLen; $j++)
if ($bin[$j] === "1") $set[] = $arr[$j];
$res[] = $set;
}
foreach($res as $k => $val)
if (!count($val) && !$include_empty) unset($res[$k]);
elseif (count($val) === $length && !$include_full) unset($res[$k]);
function cmp($a, $b){ return (count($a) - count($b)); }
if ($sort) usort($res, 'cmp');
return $res;
}
//Output Results:
foreach ($res as $key => $data) {
echo $key." -> [".(implode(',',$data))."]\r";
}
/*
0 -> [1]
1 -> [3]
2 -> [2]
3 -> [1,2]
4 -> [2,3]
5 -> [1,3]
*/
正如您所看到的,该函数处理输入数组,您可以选择是否在结果中包含空集和完整集。
你应该知道迭代次数正在急剧增加:
不删除空集或完整集:
n*(2^n)
删除:
(2^n) + n*(2^n)
删除&amp;排序(最坏情况):
(2^n) + n*(2^n) + n^2
假设我们有一个包含9个值的输入数组:
(2^9)*9 = 4608;
(2^9) + 9*(2^9) = 5120;
(2^9) + 9*(2^9) + 9^2 = 5201;
这是我所知道的最快的方式。
注意强>: 该函数需要一个唯一的数组 - 您可以确保您的数组是唯一的:
$arr = array_unique ($arr);