https://leetcode.com/problems/combination-sum/
Example 1:
Input: candidates = [2,3,5], target = 8,
A solution set is:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
candidates中每个数都是惟一的。
我的大概想法就是先排序,然后从小往大搜索,有两种选择:
- 不选当前数,指针右移
- 选当前数,指针不变
我的解法:(比较慢)
class Solution {
public:
vector<vector<int>> res;
vector<int> nums;
int M;
int getHashCode(vector<int>& nums){
int hashCode=0;
int base=1;
for(int i=0;i<nums.size();i++){
hashCode+=base*nums[i];
base*=M;
}
return hashCode;
}
set<int> numsSet;
void dfs(vector<int>& candidates,int target,int i){
int sum= accumulate(nums.begin() , nums.end() , 0);
if(sum==target){
int hashCode=getHashCode(nums);
if(numsSet.count(hashCode)==0){
res.push_back(nums);
numsSet.insert(hashCode);
}
}
else if(sum>target || i>candidates.size())
return;
else{
nums.push_back(candidates[i]);
dfs(candidates,target,i+1);
nums.pop_back();
if(i+1<candidates.size())
dfs(candidates,target,i+1);
}
}
int max(int a,int b){
return a>b?a:b;
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
int ix=max(0,candidates.size()-1);
M=candidates[ix];
dfs(candidates,target,0);
return res;
}
};
较快解法:
这个算法不像我的算法为两个分支去搜索,而是通过for循环去遍历。
class Solution {
public:
void dfs(int remain, int cur_idx, vector<int>& path, const vector<int>& cans, vector<vector<int>>& res) {
if(remain == 0) {
res.push_back(path);
return;
}
if(remain < 0) return;
for(int i = cur_idx; i < cans.size(); ++i){
if(cans[i] > remain) break;
path.push_back(cans[i]);
dfs(remain - cans[i], i, path, cans, res);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& cands, int target) {
vector<vector<int>> res;
vector<int> cur_path;
if(cands.empty()) return res;
sort(cands.begin(), cands.end());
dfs(target, 0, cur_path, cands, res);
return res;
}
};
2. Combination Sum II
https://leetcode.com/problems/combination-sum-ii/
我的C++报错:
class Solution {
public:
vector<vector<int>> res;
vector<int> nums;
int M;
int getHashCode(vector<int>& nums){
int hashCode=0;
int base=1;
for(int i=0;i<nums.size();i++){
hashCode+=base*nums[i];
base*=M;
}
return hashCode;
}
set<int> numsSet;
void dfs(vector<int>& candidates,int target,int i){
int sum= accumulate(nums.begin() , nums.end() , 0);
if(sum==target){
int hashCode=getHashCode(nums);
if(numsSet.count(hashCode)==0){
res.push_back(nums);
numsSet.insert(hashCode);
}
}
else if(sum>target || i>candidates.size())
return;
else{
nums.push_back(candidates[i]);
dfs(candidates,target,i+1);
nums.pop_back();
if(i+1<candidates.size())
dfs(candidates,target,i+1);
}
}
int max(int a,int b){
return a>b?a:b;
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
int ix=max(0,candidates.size()-1);
M=candidates[ix];
dfs(candidates,target,0);
return res;
}
};
我用Python重写了一遍
class Solution:
res = []
nums = []
def dfs(self,remain,index,candidates):
if remain==0:
import copy
self.res.append(copy.deepcopy(self.nums))
return
elif remain<0:
return
else:
for i in range(index,len(candidates)):
if remain-candidates[i]<0:
break
self.nums.append(candidates[i])
self.dfs(remain-candidates[i],index+1,candidates) # index 不 +1 的话,就是上一题的情况
self.nums.pop()
def combinationSum2(self, candidates:list, target: int) :
if not candidates:
return candidates
candidates.sort()
self.dfs(target,0,candidates)
return list(set(map(tuple,map(sorted,self.res))))
本地运行正确,提交还是报错,玄学
放弃挣扎,题解是这样的:
class Solution(object):
# slight modification on Combination Sum problem
def dfs(self, nums, target, index, path, ans):
if target < 0:
return None
if target == 0 and (path not in ans):
ans.append(path)
for i in range(index, len(nums)):
if nums[i] > target:
break
self.dfs(nums, target-nums[i], i+1, path+[nums[i]], ans)
def combinationSum2(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
ans = []
candidates.sort() # this is for the break in dfs function, which makes it much faster
self.dfs(candidates, target, 0, [], ans)
return ans
意思是入了栈就不能再出栈了。
3. Permutationshttps://leetcode.com/problems/permutations/
感觉最简单的方法就是C++的next_permutation了
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<vector<int>> ans;
do{
ans.push_back(nums);
}while(next_permutation(nums.begin(),nums.end()));
return ans;
}
};
其实本质是dfs的排列树
class Solution {
public:
vector<vector<int>> ans;
void dfs(vector<int>& nums,int ix){
if(ix==nums.size()){
ans.push_back(nums);
return;
}else{
for(int i=ix;i<nums.size();i++){
swap(nums[i],nums[ix]);
dfs(nums,ix+1);
swap(nums[i],nums[ix]);
}
}
}
vector<vector<int>> permute(vector<int>& nums) {
dfs(nums,0);
return ans;
}
};
3. Permutations II
https://leetcode.com/problems/permutations-ii/
这题如果用next_permutation 来做的话,其实也是可以的。
如果是用上题的排列树的话,需要注意一个去重的问题。
用最容易去重的python实现:
class Solution:
ans=[]
def dfs(self,nums,ix):
if ix==len(nums):
self.ans.append(nums[:])
return
else:
for i in range(ix,len(nums)):
nums[i],nums[ix]=nums[ix],nums[i]
self.dfs(nums,ix+1)
nums[i],nums[ix]=nums[ix],nums[i]
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
self.ans=[] # 多点测试,不用这个变量会累积
self.dfs(nums,0)
# return self.ans
return list(map(list,set(map(tuple,self.ans))))