每日一題——子集

菜雞每日一題系列打卡78

每天一道算法題目 

小夥伴們一起留言打卡

堅持就是勝利,我們一起努力!

題目描述(引自LeetCode)

給定一組不含重複元素的整數數組nums,返回該數組所有可能的子集(冪集)。

說明:解集不能包含重複的子集。

示例:
輸入: nums = [1,2,3]
輸出:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

題目分析

其實這道題目和上一道題目很類似,上一題是求指定集合(1 ~ n)中的任選k個元素的組合,而本題如果按照這種說法進行描述的話,就是,求給定數組nums中任選0,1,2,……,nums.length個元素的組合。

上一題我們用回溯法解決的,這道題菜雞將採用二進制排序的方式進行解決。所謂的二進制排序,就是將每個子集映射到長度爲n的位掩碼中,如果第i位掩碼爲1,則表示nums[i]在子集中;反之,如果第i位掩碼爲0,則表示nums[i]不在子集中。舉個栗子:00...00表示空子集,11...11表示全集

使用二進制排序的方法雖然時間複雜度沒有本質提高,但位運算操作實際上是比回溯法的方法調用要快很多的。話不多說,上代碼!

代碼實現

class Solution {


    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> result = new ArrayList();
        // 快速冪求取子集個數
        int n = myPow(2, nums.length);
        for (int i = 0; i < n; i++) {
            List<Integer> tmp = new ArrayList();
            // 求取每一個i對應的子集
            for (int j = 0; j < nums.length; j++) {
                if (((i >> j) & 1) == 1) tmp.add(nums[j]);
            }
            result.add(tmp);
        }
        // 返回結果
        return result;
    }


    // 快速冪
    private int myPow(int x, int n) {
        int tmp = 1;
        while (n > 1) {
            if ((n & 1) == 0) {
                x *= x;
                n >>= 1;
            } else {
                tmp *= x;
                n -= 1;
            }
        }
        return x * tmp;
    }


}

代碼分析

對代碼進行分析,程序的循環次數爲n * 2^n,因此,時間複雜度爲O(n * 2^n);而就空間而言,需要存儲所有的子集,因此,空間複雜度爲O(n * 2^n)。

執行結果

學習 | 工作 | 分享

????長按關注“有理想的菜雞

只有你想不到,沒有你學不到

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章