菜雞每日一題系列打卡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)。
執行結果
學習 | 工作 | 分享
????長按關注“有理想的菜雞”
只有你想不到,沒有你學不到