78. 子集
难度中等1058
给你一个整数数组
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>> res;
vector<int> Nums;
vector<vector<int>> subsets(vector<int>& nums) {
Nums = nums;
vector<int> temp;
subsets_help(0,temp);
return res;
}
void subsets_help(int j, vector<int> temp){
res.push_back(temp);
for(int i = j; i<Nums.size(); i++){
temp.push_back(Nums[i]);
subsets_help(i+1,temp);
temp.pop_back();
}
}
};
90. 子集 II
难度中等415
给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
**说明:**解集不能包含重复的子集。
示例:
输入: [1,2,2] 输出: [ [2], [1], [1,2,2], [2,2], [1,2], [] ]
class Solution {
public:
vector<vector<int>> res;
vector<int> Nums;
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(),nums.end());
Nums = nums;
vector<int> temp;
subsetsWithDup_helper(0, temp);
return res;
}
void subsetsWithDup_helper(int j, vector<int> temp){
res.push_back(temp);
for(int i = j;i<Nums.size();i++){
if(i>j && Nums[i]== Nums[i-1]) continue;//这轮的点和上一轮的点重复没关系,但是新加入的点不能和这轮重复
temp.push_back(Nums[i]);
subsetsWithDup_helper(i+1,temp);
temp.pop_back();
}
}
};
77. 组合
难度中等525
给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
示例:
输入: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
class Solution {
public:
int N;
int K;
vector<vector<int>> res;
vector<vector<int>> combine(int n, int k) {
N = n; K = k;
vector<int> temp;
combine_helper(1,temp);
return res;
}
void combine_helper(int j, vector<int> temp){
if(temp.size()==K) {
res.push_back(temp);
return;
}
for(int i=j;i<=N-(K-temp.size())+1;i++){//优化剪枝,删去无数可选的情况
temp.push_back(i);
combine_helper(i+1,temp);
temp.pop_back();
}
}
};
39. 组合总和
难度中等1220
给定一个无重复元素的数组
candidates
和一个目标数target
,找出candidates
中所有可以使数字和为target
的组合。
candidates
中的数字可以无限制重复被选取。说明:
- 所有数字(包括
target
)都是正整数。- 解集不能包含重复的组合。
示例 1:
输入:candidates = [2,3,6,7], target = 7, 所求解集为: [ [7], [2,2,3] ]
示例 2:
输入:candidates = [2,3,5], target = 8, 所求解集为: [ [2,2,2,2], [2,3,3], [3,5] ]
提示:
1 <= candidates.length <= 30
1 <= candidates[i] <= 200
candidate
中的每个元素都是独一无二的。1 <= target <= 500
class Solution {
public:
vector<vector<int>> res;
vector<int> Can;
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<int> temp;
sort(candidates.begin(),candidates.end());
Can = candidates;
combinationSum_helper(target, 0,temp);
return res;
}
void combinationSum_helper(int target,int start,vector<int> temp){
if(target==0){
res.push_back(temp);
return;
}
if(target<0)return;
for(int i= start;i< Can.size();i++ ){
temp.push_back(Can[i]);
combinationSum_helper(target-Can[i],i,temp);
temp.pop_back();
}
}
};
40. 组合总和 II
难度中等528
给定一个数组
candidates
和一个目标数target
,找出candidates
中所有可以使数字和为target
的组合。
candidates
中的每个数字在每个组合中只能使用一次。说明:
- 所有数字(包括目标数)都是正整数。
- 解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8, 所求解集为: [ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5, 所求解集为: [ [1,2,2], [5] ]
class Solution {
public:
vector<vector<int>> res;
vector<int> Candidates;
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
Candidates = candidates;
vector<int> temp;
combinationSum2_helper(target,0,temp);
return res;
}
void combinationSum2_helper(int target,int start, vector<int> temp){
if(target==0){
res.push_back(temp);
return;
}
if(target <0 )return;
for(int i=start;i<Candidates.size();i++){
if(i>start && Candidates[i]==Candidates[i-1])continue;
if(target<Candidates[i]) return; //剪枝!
temp.push_back(Candidates[i]);
combinationSum2_helper(target-Candidates[i],i+1,temp);
temp.pop_back();
}
}
};
46. 全排列
难度中等1219
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
class Solution {
public:
vector<vector<int>> res;
vector<int> Nums;
vector<vector<int>> permute(vector<int>& nums) {
Nums = nums;
vector<int> temp;
vector<bool> used(nums.size(),false);
permute_helper(0,temp,used);
return res;
}
void permute_helper(int start,vector<int> temp,vector<bool> used){
if(temp.size()== Nums.size()){
res.push_back(temp);
return;
}
for(int i = 0;i<Nums.size();i++){
if(used[i]==true) continue;
temp.push_back(Nums[i]);
used[i]=true;
permute_helper(i+1,temp,used);
temp.pop_back();
used[i] = false;
}
}
};
47. 全排列 II
难度中等632
给定一个可包含重复数字的序列
nums
,按任意顺序 返回所有不重复的全排列。示例 1:
输入:nums = [1,1,2] 输出: [[1,1,2], [1,2,1], [2,1,1]]
示例 2:
输入:nums = [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
提示:
1 <= nums.length <= 8
-10 <= nums[i] <= 10
class Solution {
public:
vector<int> Nums;
vector<vector<int>> res;
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(),nums.end());
Nums = nums;
vector<int> temp;
vector<bool> used(nums.size(),false);
permuteUnique_helper(temp,used);
return res;
}
void permuteUnique_helper(vector<int> temp,vector<bool> used){
if(temp.size()== Nums.size()){
res.push_back(temp);
return;
}
for(int i=0;i<Nums.size();i++){
if(used[i])continue;
if( i>0 && Nums[i] == Nums[i-1] && used[i-1]) continue;
temp.push_back(Nums[i]);
used[i] = true;
permuteUnique_helper(temp,used);
temp.pop_back();
used[i] = false;
}
}
};
17. 电话号码的字母组合
难度中等1190
给定一个仅包含数字
2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dKBBBlkf-1627477236813)(回溯.assets/17_telephone_keypad.png)]
示例 1:
输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = "" 输出:[]
示例 3:
输入:digits = "2" 输出:["a","b","c"]
提示:
0 <= digits.length <= 4
digits[i]
是范围['2', '9']
的一个数字。
class Solution {
public:
vector<string> letter={"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
string Digits;
vector<string> res;
vector<string> letterCombinations(string digits) {
Digits = digits;
string temp;
if(digits.empty()) return res;
letterCombinations_helper(0,temp);
return res;
}
void letterCombinations_helper(int start, string temp){
if(temp.size()==Digits.size()){
res.push_back(temp);
return;
}
for(int i = 0;i<letter[Digits[start]-'2'].size();i++){
temp.push_back(letter[Digits[start]-'2'][i]);
letterCombinations_helper(start+1,temp);
temp.pop_back();
}
}
};
320. 列举单词的全部缩写
难度中等52
请你写出一个能够举单词全部缩写的函数。
**注意:**输出的顺序并不重要。
示例:
输入: "word" 输出: ["word", "1ord", "w1rd", "wo1d", "wor1", "2rd", "w2d", "wo2", "1o1d", "1or1", "w1r1", "1o2", "2r1", "3d", "w3", "4"]
class Solution {
public:
vector<string>res;
string Word;
vector<string> generateAbbreviations(string word) {
Word = word;
string temp;
generateAbbreviations_helper(0,0,temp);
return res;
}
void generateAbbreviations_helper(int start, int num, string temp){
if(start == Word.size()){
if(num==0) res.push_back(temp);
else{
temp+=to_string(num);
res.push_back(temp);
}
return;
}
//start字母被缩写
generateAbbreviations_helper(start+1,num+1,temp);
//start不被缩写
int currentLength = temp.size();
if(num!=0)temp+=to_string(num);
temp.push_back(Word[start]);
generateAbbreviations_helper(start+1,0,temp);
temp.resize(currentLength);
}
};
254. 因子的组合
难度中等71
整数可以被看作是其因子的乘积。
例如:
8 = 2 x 2 x 2; = 2 x 4.
请实现一个函数,该函数接收一个整数 n 并返回该整数所有的因子组合。
注意:
- 你可以假定 n 为永远为正数。
- 因子必须大于 1 并且小于 n。
示例 1:
输入: 1 输出: []
示例 2:
输入: 37 输出: []
示例 3:
输入: 12 输出: [ [2, 6], [2, 2, 3], [3, 4] ]
示例 4:
输入: 32 输出: [ [2, 16], [2, 2, 8], [2, 2, 2, 4], [2, 2, 2, 2, 2], [2, 4, 4], [4, 8] ]
class Solution {
public:
vector<vector<int>> res;
vector<vector<int>> getFactors(int n) {
vector<int> temp;
getFactors_helper(n,2,temp);
return res;
}
void getFactors_helper(int target,int start,vector<int> temp){
if(target==1){
if(temp.size()>1)res.push_back(temp);
}
for(int i=start;i*i<=target;i++){
if(target%i!=0 ) continue;
//这轮加入
temp.push_back(i);
temp.push_back(target/i);
res.push_back(temp);
//继续分解
temp.pop_back();
getFactors_helper(target/i,i,temp);
temp.pop_back();
}
}
};
剑指 Offer 38. 字符串的排列
难度中等243
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = "abc" 输出:["abc","acb","bac","bca","cab","cba"]
1.生成法(没有剪枝,使用set在输出时去重)
class Solution {
public:
unordered_set<string> res;
int strSize;
string S;
vector<string> permutation(string s) {
string temp;
strSize = s.size();
S = s;
vector<bool> used(strSize,false);
permutation_help(used,temp,s.size());
vector<string> vecRes;
for(auto i:res){
vecRes.push_back(i);
}
return vecRes;
}
void permutation_help(vector<bool>used, string temp,int remain){
if(remain==0)
res.emplace(temp);
for(int i=0;i<strSize;i++){
if(used[i])continue;
used[i] = true;
temp += S[i];
permutation_help(used, temp,remain-1);
temp.pop_back();
used[i] = false;
}
}
};
2.交换法(有剪枝)
class Solution {
public:
vector<string> permutation(string s) {
dfs(s, 0);
return res;
}
private:
vector<string> res;
void dfs(string s, int x) {
if(x == s.size() - 1) {
res.push_back(s); // 添加排列方案
return;
}
set<int> st;
for(int i = x; i < s.size(); i++) {
if(st.find(s[i]) != st.end()) continue; // 重复,因此剪枝
st.insert(s[i]);
swap(s[i], s[x]); // 交换,将 s[i] 固定在第 x 位
dfs(s, x + 1); // 开启固定第 x + 1 位字符
swap(s[i], s[x]); // 恢复交换
}
}
};
法(有剪枝)
class Solution {
public:
vector<string> permutation(string s) {
dfs(s, 0);
return res;
}
private:
vector<string> res;
void dfs(string s, int x) {
if(x == s.size() - 1) {
res.push_back(s); // 添加排列方案
return;
}
set<int> st;
for(int i = x; i < s.size(); i++) {
if(st.find(s[i]) != st.end()) continue; // 重复,因此剪枝
st.insert(s[i]);
swap(s[i], s[x]); // 交换,将 s[i] 固定在第 x 位
dfs(s, x + 1); // 开启固定第 x + 1 位字符
swap(s[i], s[x]); // 恢复交换
}
}
};