算法训练营day28_回溯算法(2.28)
93.复原IP地址
直接在原字符串上操作加.减.;
函数返回值void,参数字符串s,位置u,标点数目;
递归出口,标点数目3个的时候,判断最后一段是否合法,若合法就把字符串放入ans;
for循环遍历的时候,字符字串合法才会dfs下一层,若不合法,直接break,后面的更长,更不会合法;
class Solution {
public:
vector<string> ans;
bool check(string s,int l,int r){
if(l>r) return false;
if(s[l]=='0'&&l!=r) return false;
if(r-l+1>3) return false;
int sum=0;
for(int i=l;i<=r;i++){
if(s[i]>'9'||s[i]<'0') return false;
sum=sum*10+s[i]-'0';
}
return sum<=255;
}
void dfs(string s,int u,int cnt){
if(cnt==3){
if(check(s,u,s.size()-1)){
ans.push_back(s);
}
}
for(int i=u;i<s.size();i++){
if(check(s,u,i)){
s.insert(s.begin()+i+1,'.');
dfs(s,i+2,cnt+1);
s.erase(s.begin()+i+1);
}
else break;
}
return;
}
vector<string> restoreIpAddresses(string s) {
ans.clear();
if(s.size()<4||s.size()>12) return ans;
dfs(s,0,0);
return ans;
}
};
78.子集
组合数,不光叶子节点,每个节点都要放到ans里;
class Solution {
public:
vector<vector<int>> ans;
vector<int> V;
void dfs(vector<int> nums,int u){
ans.push_back(V);
if(u>=nums.size()) return;
for(int i=u;i<nums.size();i++){
V.push_back(nums[i]);
dfs(nums,i+1);
V.pop_back();
}
return;
}
vector<vector<int>> subsets(vector<int>& nums) {
ans.clear();
V.clear();
dfs(nums,0);
return ans;
}
};
90.子集II
树层需要去重,加上个st标记数组;
class Solution {
public:
vector<int> V;
vector<vector<int>> ans;
void dfs(vector<int> nums,int u,vector<bool> st){
ans.push_back(V);
if(u>=nums.size()) return;
for(int i=u;i<nums.size();i++){
if(i>=1&&nums[i]==nums[i-1]&&st[i-1]==false) continue;
V.push_back(nums[i]);
st[i]=true;
dfs(nums,i+1,st);
V.pop_back();
st[i]=false;
}
return;
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<bool> st(nums.size(),false);
ans.clear();
V.clear();
dfs(nums,0,st);
return ans;
}
};