93. 复原 IP 地址 - 力扣(LeetCode)
思路:使用字符'.'做分隔标记,当'.'有三个时且各项规则都符合,就表示分割的为正确答案
重点:使用'.'做分割标记,添加标记后起始位要加2
class Solution {
public:
vector<string>ans;
bool isvalid(string& s,int l,int r){
if(l>r){
return false;
}
if(s[l]=='0'&&l!=r){
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');
if(sum>255){
return false;
}
}
return true;
}
void dfs(string& s,int index,int point){
if(point==3){
if(isvalid(s,index,s.size()-1)){
ans.push_back(s);
return;
}
}
for(int i=index;i<s.size();i++){
if(isvalid(s,index,i)){
s.insert(s.begin()+i+1,'.');
dfs(s,i+2,point+1);
s.erase(s.begin()+i+1);
}else{
break;
}
}
}
vector<string> restoreIpAddresses(string s) {
dfs(s,0,0);
return ans;
}
};
78. 子集 - 力扣(LeetCode)
思路:回溯算法,每次递归开始时存储子集
class Solution {
public:
vector<vector<int>>ans;
vector<int>path;
void dfs(vector<int>&nums,int index){
ans.push_back(path);
if(index==nums.size()){
return;
}
for(int i=index;i<nums.size();i++){
path.push_back(nums[i]);
dfs(nums,i+1);
path.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
dfs(nums,0);
return ans;
}
};
90. 子集 II - 力扣(LeetCode)
思路:回溯算法,每次递归开始时存储子集,再使用去重逻辑去重
重点:前一个标记为false时,表示是回溯回来的表示在同一层,所以需要去重。
class Solution {
public:
vector<vector<int>>ans;
vector<int>path;
void dfs(vector<int>& nums,int index,vector<bool>& t){
ans.push_back(path);
if(nums.size()==index){
return;
}
for(int i=index;i<nums.size();i++){
if(i>0&&nums[i]==nums[i-1]&&t[i-1]==false){
continue;
}
path.push_back(nums[i]);
t[i]=true;
dfs(nums,i+1,t);
t[i]=false;
path.pop_back();
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<bool>t(nums.size(),false);
sort(nums.begin(),nums.end());
dfs(nums,0,t);
return ans;
}
};
总结
需要在字符串中加入同一个字符时,使用添加的字符做标记进行分割。子集问题在每次递归开始时统计。去重使用树枝和树层去重逻辑,前一个标记为false时表示是回溯回来的表示在同一层,所以需要去重。