求解一个数组的所有子集

已知一个数组,求出这个数组的所有子集

之前看到这样一个这样的问题,第一反应是排列组合,但后来一想不容易实现。闲着无事,不如把这道题当做一个练习题练习一下,也发现 php 原生函数组合起来可以实现好多东西,就是不太容易组合使用,这里记录一下解题方法

1. 思考从何处下手去解决子集

我们都知道一个含有 n 个元素的集合,它的子集共有 2^n 个,其中必有一个为空集,这里我们不考虑空集,只需求出它的真子集。

对于集合中的每一个元素,都可以被选,也可以不被选,这也就解释了 2^n 从何而来,此处,我们就利用这个思路来处理这个问题。我们用 0 表示不选择元素,用 1 表示选择元素,故我们可以生成 0/1 序列来解决子集问题。

我们可以利用二进制实现 0/1 序列的生成,n 个元素的集合,真子集共有 2^n - 1 个,每一个数字都是一个二进制的 0/1 序列

还有一个问题是10进制转化为2进制时,前面的 0 会被省略,我们需要上去

2.代码实现,一步步解决问题

class one
{
    public static function work($arr){
        $num = count($arr);// 统计一个数组元素个数
        $min = 1;
        $max = bindec(str_repeat('1', $num));// 用二进制求得 2^n - 1
        for($i = $min;$i <= $max;$i++){
            $str[] = str_pad(decbin($i), $num, '0', STR_PAD_LEFT);
            // 数字转化为2进制并补充前面的隐含 0
        }
        // case 1 下面注释代码为第一次尝试,无法保留键值,无法处理含有相同值得数组
        /*
        foreach($str as $v){
            $choose = str_split($v, 1);
            $temparr = array_combine($arr, $choose);// 数组值作为键值, 便于下面选出
            $out[] = array_keys($temparr, 1);
        }
        return $out;
        */
        // case 2 如下 考虑数组 $arr 的键值肯定是唯一性的,所以修改为选择键值,可处理任意数组并保留键
        foreach($str as $v){
            $choose = str_split($v, 1);// 将0/1序列转化为数组
            // 将数组键值取出与0/1数组合并
            $temparr = array_combine(array_keys($arr), $choose);
            //将 值为 1 的键值取出
            $keys = array_keys($temparr, 1);
            $s = null;// 定义一个空值,用来临时保存一个 子集数组
            foreach($keys as $value){
                $s[$value] = $arr[$value];
                // 如果键值被上面选中,则子集数组中也储存这个值
            }
            $out[] = $s;
        }
        return $out;
    }
}

print_r(one::work(['s'=>1, 'k'=>8, 'd'=>3])); // 测试一下

// 结果如下
Array
(
    [0] => Array
        (
            [d] => 3
        )

    [1] => Array
        (
            [k] => 8
        )

    [2] => Array
        (
            [k] => 8
            [d] => 3
        )

    [3] => Array
        (
            [s] => 1
        )

    [4] => Array
        (
            [s] => 1
            [d] => 3
        )

    [5] => Array
        (
            [s] => 1
            [k] => 8
        )

    [6] => Array
        (
            [s] => 1
            [k] => 8
            [d] => 3
        )

)
// 到达了希望的效果

php 书册中的函数灵活使用可以解决很多问题,以后需要多多练习,让自己更加熟悉

本作品采用《CC 协议》,转载必须注明作者和本文链接
一起学习,共同进步
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
1
粉丝
0
喜欢
1
收藏
0
排名:1898
访问:1142
私信
所有博文
博客标签
社区赞助商