組合、排列、子集 - a920604a/leetcode GitHub Wiki
-
46 Permutations
-
47 Permutations II
-
31 Next Permutation
-
784 Letter Case Permutation
-
78 Subsets
-
90 Subsets II
-
2597 The Number of Beautiful Subsets
-
77 Combinations
-
39 Combination Sum
-
40 Combination Sum II
-
216 Combination Sum III
組合與排列最大差異,排列是有順序,組合沒有順序,所以排列數通常較大
-
排列,每個元素都必須包含,所以每次都需要重頭拜訪,需要額外vector used來紀錄該元素是否拜訪過。當然也可迴圈遍歷find()檢查其值是否已包含,但較費時且也較不泛化。
-
組合沒有順序性可言,不必重頭拜訪,所以可以事先用排序,在借助vector used 或 if(i > s && nums[i] == nums[i-1]) continue; 條件語句。
-
子集,沒有順序性可言,不必重頭拜訪。紀錄拜訪樹的每個路徑,不拜訪錯過的
-
陣列有重複元素,可以排序,搭配if(i > s && nums[i] == nums[i-1]) continue;,去掉重複元素,或是vector used,去掉重複元素
-
78 Subsets
-
90 Subsets II
-
784 Letter Case Permutation
DFS
void traverse(int l, int r, int k, vector<int> &path, vector<vector<int>> &ret){
if(path.size() == k){
ret.push_back(path);
return;
}
for(int i=l;i<=r;++i){
path.push_back(i);
traverse(i+1, r, k, path, ret);
path.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> ret;
vector<int> path;
traverse(1, n, k, path, ret);
return ret;
}
void traverse(int s, vector<int> &candidates, int target, vector<vector<int>>&ret, vector<int> &path){
// base case
if(target <0) return;
if(target == 0){
ret.push_back(path);
return;
}
for(int i=s;i<candidates.size() ;++i){
path.push_back(candidates[i]);
traverse(i, candidates, target - candidates[i], ret, path);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> ret;
vector<int> path;
traverse(0, candidates, target, ret, path);
return ret;
}
vector<vector<int>> ret;
void traverse(vector<int>& candidates, int target, int l, int r, vector<int>&path){
if(target<0) return;
if(target==0){
ret.push_back(path);
}
for(int i=l;i<=r ;++i){
if (i == l || candidates[i] != candidates[i - 1]){
path.push_back(candidates[i]);
traverse(candidates, target-candidates[i], i+1,r, path);
path.pop_back();
}
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
vector<int> path;
traverse(candidates, target, 0,candidates.size()-1 , path);
return ret;
}
vector<vector<int>> ret;
void traverse(int start, int k, int target, vector<int> &path ){
if(target<0) return;
if(target==0) {
if(path.size() == k) ret.push_back(path);
return;
}
for(int i=start ;i<=9;++i){
// if(cur + i > n) break;
path.push_back(i);
traverse(i+1, k, target-i, path);
path.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
vector<int> path;
traverse(1, k, n, path);
return ret;
vector<vector<int>> ret;
void traverse(vector<int>& nums, vector<int>& path){
if(path.size() == nums.size()){
ret.push_back(path);
return;
}
for(int i=0;i<nums.size(); ++i){
if(find(path.begin(), path.end(), nums[i])!=path.end()) continue;
path.push_back(nums[i]);
traverse(nums, path);
path.pop_back();
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<int> path;
traverse(nums, path);
return ret;
}
set<vector<int>> ret;
void traverse(vector<int> & nums, vector<int> &path, vector<bool> & visited){
if(path.size() == nums.size()){
// ret.push_back(path);
ret.insert(path);
return;
}
for(int i=0; i<nums.size() ;++i){
if(visited[i]) continue;
visited[i] = true;
path.push_back(nums[i]);
traverse(nums, path, visited);
visited[i] = false;
path.pop_back();
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<int> path;
vector<bool> visited(nums.size(), false);
traverse(nums, path, visited);
return vector<vector<int>>(ret.begin(), ret.end());
}
void nextPermutation(vector<int>& nums) {
int n = nums.size();
int k;
for(k = n-2;k>-1 ;k--){
if(nums[k]<nums[k+1]) break;
}
if(k<0){
reverse(nums.begin(), nums.end());
}
else{
int j ;
for(j = n-1;j>k;j--){
if(nums[j]> nums[k]) break;
}
swap(nums[j], nums[k]);
reverse(nums.begin() + k+1, nums.end());
}
}
vector<string> ret;
void traverse(string &s, string &path, int l){
if(path.size() == s.size()){
ret.push_back(path);
}
// if(l>= s.size()) reutrn;
for(int i=l;i<s.size();++i){
// 因為只會有大小寫與數字
if(s[i] >='0' && s[i]<='9'){
path.push_back(s[i]);
traverse(s, path, i+1);
path.pop_back();
}
// if(( s[i]>='a' && s[i]<='z') || (s[i]>='A' && s[i]<='Z')){
else{
// 選擇小寫
path.push_back(tolower(s[i]));
traverse(s, path, i+1);
path.pop_back();
// 選擇大寫
path.push_back(toupper(s[i]));
traverse(s, path, i+1);
path.pop_back();
}
}
}
vector<string> letterCasePermutation(string s) {
string path;
traverse(s, path, 0);
return ret;
}
vector<vector<int>> ret;
void traverse(vector<int> &nums, vector<int>&path, int l){
ret.push_back(path);
// if(l>=nums.size()) return;
for(int i=l;i<nums.size();++i){
path.push_back(nums[i]);
traverse(nums, path, i+1);
path.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
vector<int> path;
traverse(nums, path, 0);
return ret;
}
vector<vector<int>> ret;
void traverse(vector<int> &nums, vector<int>&path, int l){
ret.push_back(path);
for(int i=l;i<nums.size();++i){
if(i>l || nums[i-1]!=nums[i]){
path.push_back(nums[i]);
traverse(nums, path, i+1);
path.pop_back();
}
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<int> path;
traverse(nums, path, 0);
return ret;
}
class Solution {
public:
vector<vector<int>> ret;
void traverse(int n, int k, vector<int> & path, int start){
// 終止條件
if(path.size() ==k){
ret.push_back(path);
return;
}
for(int i=start;i<=n;++i){
path.push_back(i);
// [2,4] OK , [4,2] not OK -> 只允許遞增,避免重複
traverse(n,k,path, i+1);
path.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
vector<int> path;
traverse(n,k,path, 1);
return ret;
}
};
class Solution {
public:
vector<vector<int>> ret;
void traverse(vector<int>& candidates, int target, vector<int>& path, int s){
// 終止條件
if(target<0) return;
if(target==0){
ret.push_back(path);
return;
}
for(int i=s;i<candidates.size();++i){
// option
if(target < candidates[i]) return;
path.push_back(candidates[i]);
// 因為可重複拿取同一元素
traverse(candidates, target-candidates[i], path, i);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
vector<int> path;
traverse(candidates, target, path, 0);
return ret;
}
};
class Solution {
public:
vector<vector<int>> ret;
void traverse(vector<int>& candidates, int target, vector<int> & path, int j){
if(target<0 ) return;
if(target==0){ret.push_back(path); return;}
for(int i=j;i<candidates.size();++i){
if(i>j && candidates[i-1] == candidates[i]) continue;
path.push_back(candidates[i]);
traverse(candidates, target-candidates[i], path, i+1);
path.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
vector<int> path;
traverse(candidates, target, path, 0);
return ret;
}
};
class Solution {
public:
vector<vector<int>> ret;
void traverse(int k, int n, int j, vector<int>& path){
if(k == path.size()){
if(n==0) ret.push_back(path);
return;
}
for(int i = j;i<=9;++i){
path.push_back(i);
traverse(k, n-i, i+1, path);
path.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
vector<int> path;
traverse(k, n, 1, path);
return ret;
}
};