这是两个比较基础的搜索题(dfs),可能也叫做回溯法,个人觉得dfs一般都会有回溯,第一问比较简单,每次进入一个状态就把当前状态加入到ans中,如何只要在搜索过程中,记录当前的起点是第几个数,然后从该数往下搜索即可,注意保留现场,也就是push_back后还得pop_back,代码如下:
vector<vector<int> >ans;
vector<int>tmp;
void solve(int dep, vector<int> &S)
{
ans.push_back(tmp);
if (dep == S.size())
return;
int i;
for (i = dep; i<S.size(); i++)
{
tmp.push_back(S[i]);
solve(i+ 1, S);
tmp.pop_back();
}
return;
}
class Solution {
public:
vector<vector<int> > subsets(vector<int> &S) {
int i;
ans.clear();
sort(S.begin(), S.end());
tmp.clear();
solve(0, S);
return ans;
}
};
第二位的关键就是如何去除重复的搜索,比如有1,2,2,3,那么其实第二个2和第三个2往下搜的结果都是一样的subset,只需要搜索他们其中的一个即可,那么可以这样判断,因为只有两个数相等时才会重复搜索,只要每次判断当前数是否和前一个数相等,如果相等,就不需要搜下去,因为前一次搜过了,不相等则继续往下搜,当然对于枚举的第一个数,他没有前一个数,所以他肯定要搜,并且前面搜索策略也保证了枚举的第一个数不可能是多个相同的数的非第一个(即第二个到最后一个),这其实是非常经典的剪枝。代码如下:
vector<vector<int> >ans;
vector<int>tmp;
void solve(int dep, vector<int> &S)
{
ans.push_back(tmp);
if (dep == S.size())
return;
int i;
int cl = 1;
for (i = dep; i<S.size(); i++)
{
if (i == dep)
{
tmp.push_back(S[i]);
solve(i + 1, S);
tmp.pop_back();
}
else if (i > dep&&S[i] != S[i - 1])
{
tmp.push_back(S[i]);
solve(i + 1, S);
tmp.pop_back();
}
}
return;
}
class Solution {
public:
vector<vector<int> > subsetsWithDup(vector<int> &S) {
int i;
ans.clear();
sort(S.begin(), S.end());
tmp.clear();
solve(0, S);
return ans;
}
};