子集
给你一个整数数组 nums
,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
nums
中的所有元素 互不相同
分析
题目要求获得数组的所有可能的子集,需要穷举所有可能性,回溯算法是纯暴力搜索,回溯法是一种思想,通常采用递归法实现。
代码实现
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int> >res;
vector<int>path;
helper(res, nums, path, 0);
return res;
}
void helper(vector<vector<int> >& res, vector<int>& nums, vector<int>& path, int start){
res.push_back(path);
for(int i = start; i < nums.size(); i++){
path.push_back(nums[i]);
helper(res, nums, path, i + 1);
path.pop_back();
}
}
};
子集II
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例 1:
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
分析:包含重复元素,如果前面已经选择过一个相同的数字了,选择该数时则跳过,如 [1, 2, 2 ],当path = [1], 此时选择最后的2加入时,因为前面已经出现过[ 1, 2 ],所以跳过选择。
因为需要判断与上一个数字是否重复,并且子集可以按任意顺序排列,需要给nums数组排序。
代码实现:
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int> > res;
vector<int> path;
sort(nums.begin(), nums.end());
backtrack(nums, res, path, 0);
return res;
}
void backtrack(vector<int>& nums, vector<vector<int> >& res, vector<int>& path, int idx){
if(idx > nums.size()) return;
res.push_back(path);
for(int i = idx; i < nums.size(); i++){
if(i != idx && nums[i] == nums[i - 1]) continue;
path.push_back(nums[i]);
backtrack(nums, res, path, i + 1);
path.pop_back();
}
}
};
回溯算法模板
(组合问题,字符串切割问题,子集问题,排列问题,棋盘问题等)
res = []
path = []
def backtrack(未探索区域, res, path): #未探索区域一般借助下标索引实现
if path 满足条件:
res.add(path) # 深度拷贝
return # 如果不用继续搜索需要 return
for 选择 in 未探索区域当前可能的选择:
if 当前选择符合要求:
path.add(当前选择) #做选择
backtrack(新的未探索区域, res, path)
path.pop() #撤销选择
选数
题目描述
已知 n 个整数 x1,x2,…,xn,以及1个整数k(k<n)。从n个整数中任选k个整数相加,可分别得到一系列的和。例如当n=4,k=3,4个整数分别为3,7,12,19时,可得全部的组合与它们的和为:
3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29。
输入格式
键盘输入,格式为:
n,k(1≤n≤20,k<n)
x1,x2,…,xn(1≤xi≤5000000)
输出格式
屏幕输出,格式为: 1个整数(满足条件的种数)。
输入输出样例
输入
4 3 3 7 12 19
输出
1
int nums[22];
int visited[22];
int res;
bool check(int N) {
for (int i = 2; i < N; i++) {
if (N % i == 0) return false;
}
return true;
}
void dfs(int start, int n, int k, vector<int>& path) {
if (path.size() == k) {
int sum = accumulate(path.begin(), path.end(), 0);
if (check(sum)) res++;
}
for (int i = start; i <= n; i++) {
if (!visited[i]) {
path.push_back(nums[i]);
visited[i] = 1;
dfs(i, n, k, path);
visited[i] = 0;
path.pop_back();
}
}
}
int main() {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> nums[i];
}
vector<int> path;
dfs(1, n, k, path);
cout << res;
system("PAUSE");
}