求解一個陣列的所有子集

mlover發表於2019-03-28

已知一個陣列,求出這個陣列的所有子集

之前看到這樣一個這樣的問題,第一反應是排列組合,但後來一想不容易實現。閒著無事,不如把這道題當做一個練習題練習一下,也發現 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 協議》,轉載必須註明作者和本文連結

一起學習,共同進步

相關文章