39. Combination Sum
Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:
- All numbers (including target) will be positive integers.
- The solution set must not contain duplicate combinations.
For example, given candidate set [2, 3, 6, 7]
and target 7
,
My Thought
题目的大致意思:
给定一个非负整数的集合(不包含重复元素),以及给定一个目标数字 T,给出集合所有的子集,满足以下三个条件:
- 该子集所有元素之和为目标数字 T
- 每个子集允许元素重复
- 不允许有相同的子集
给定的集合很规范:非负而且不包含重复元素。
看到数列先排序。这样按顺序遍历获得的解一定不重复。
想法:
从小到大排完列表后,递归求解。
我们要在对于 (sorted list) 范围 ([0,n-1])中求解子集满足题意。
记:
- 目标整数记为 (t)
- 求解过程为 (find)
- 遍历数组C下标,记为 (i)
则递归形式:
[find(i,t,n-1) = C[i] + find(i, t-C[i],n-1)
]
这个递推公式包含了重复元素利用的情况((f(i,...)=C[i]+f(i,...)))
伪代码:
sort(C); // C范围:[0,n-1]
// vector v:用来暂存一个解
// begin:当前处理下标
PROCEDURE find(v,target,begin)
if target<C[index]
return
if binary_search(begin,n-1)!= FALSE
v.push(SN) //SN为二分搜索找到的元素
ret.push(v)
for i = beg to n-1 do
temp = v
temp.push(C[i])
find(temp, target-C[i],i)
Code(C++ 16ms)
class Solution {
public:
vector<vector<int>> ret;
vector<int> v;
// binary search
int bs(vector<int>&nums, int l,int h, int t){
if(l<=h){
int mid = (l+h)/2;
if(nums[mid]<t)
return bs(nums,mid+1,h,t);
else if(nums[mid]>t)
return bs(nums,l,mid-1,t);
return mid;
}
return -1;
}
bool find(vector<int> vv,int n,int beg){
if(n<v[beg])
return false;
int pos=bs(v,beg,v.size()-1,n);
vector<int > temp=vv;
if(pos!=-1){
temp.push_back(v[pos]);
ret.push_back(temp);
}
for(int i=beg;i<v.size();++i){
temp=vv;
temp.push_back(v[i]);
find(temp, n-v[i], i);
}
return false;
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
v = candidates;
vector<int> vv;
find(vv,target,0);
return ret;
}
};