93.复原IP地址
文档讲解:代码随想录
视频讲解: 回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址
状态:
本题本质也是分割字符串,只不过根据IP地址,必须分割三次,每一段最多三个数,所以对于原始字符串其长度应当在4-12
- 终止条件:当我们分割了3次就应该停止分割,所以我们应当在递归函数的参数中传入一个数来统计当前的递归层数
- 单层递归逻辑:同样是对于每一层使用i来控制划分的字符串,然后判断该字符串是否是合理的ip字段,如果合理那么就加入,然后递归,递归结束后再回溯
具体代码
//只能分割3次,
//每一段最多三个数
//s的长度4-12
class Solution {
private:
vector<string> res;
string ippath;
public:
bool checkpath(string s)
{
//当当前字段长度大于3或者为空,不应该添加
if(s.size()>3 || s.size() == 0)
{
return false;
}
//当当前字段长度大于1,但首字母为0,也要跳过
if(s.size()>1 && s[0] == '0')
{
return false;
}
int num = 0;
for(int i = 0;i<s.size();i++)
{
int temp = s[i]-'0';
num *= 10;
num += temp;
}
//当当前字段的大小大于255 跳过
if(num > 255)
{
return false;
}
return true;
}
void getIp(string s,int startIndex,int count)
{
//当分割了3次,开始准备填入结果数组
if(count == 3)
{
//验证剩余的字段是否合理,合理的话就添加
//不合理说明这组分割都不合理就舍去
string str = s.substr(startIndex,s.size());
if(checkpath(str))
{
ippath += str;
res.push_back(ippath);
}
return;
}
for(int i = startIndex;i<s.size();i++)
{
//分割字符串
string str = s.substr(startIndex,i-startIndex+1);
//记录添加前的长度,方便回溯
int len = ippath.size();
if(checkpath(str))
{
//合理的话,就添加str
ippath += str;
ippath += '.';
getIp(s,i+1,count+1);
//回溯
ippath.erase(len,len+str.size()+1);
cout << ippath;
}
}
return ;
}
public:
vector<string> restoreIpAddresses(string s) {
if(s.size()<4 || s.size()>12)
{
return {};
}
getIp(s,0,0);
return res;
}
};
78.子集
文档讲解:代码随想录
视频讲解: 回溯算法解决子集问题,树上节点都是目标集和! | LeetCode:78.子集
状态
这道题就是要记录每一层的每一个节点的结果,那么我们需要在每一层递归开始的时候就需要压入返回数组。
- 返回条件:就是当现在这个节点是数组最后一个数的时候就需要返回了,那么就是startIndex == nums.size(),因为还需要将最后一个记过压入res中。

具体代码
//对于每一个结果都需要存储到数组中
class Solution {
private:
vector<vector<int>> res;
vector<int> path;
public:
void getSets(vector<int>& nums, int startIndex)
{
if(startIndex >= nums.size())
{
res.push_back(path);
return;
}
else
{
res.push_back(path);
}
for(int i= startIndex;i<nums.size();i++)
{
path.push_back(nums[i]);
getSets(nums,i+1);
path.pop_back();
}
return ;
}
public:
vector<vector<int>> subsets(vector<int>& nums) {
getSets(nums,0);
return res;
}
};
90.子集II
文档讲解:代码随想录
视频讲解: 回溯算法解决子集问题,如何去重?| LeetCode:90.子集II
状态
这个需要去重,思考去重的逻辑,只需要对处于同一层的重复元素进行跳过操作,对一个树枝上的重复元素可以保留。
去重之前先排序!!!
和之前一样利用一个used数组记录判断当前的元素和前一个元素是否在同一层还是同一级。
具体代码
class Solution {
private:
vector<vector<int>> res;
vector<int> path;
public:
void getSets(vector<int>& nums, vector<int> used, int startIndex)
{
res.push_back(path);
if(startIndex == nums.size())
{
return;
}
for(int i = startIndex;i<nums.size();i++)
{
if(i>0 && used[i-1] == 0 && nums[i-1] == nums[i])
{
continue;
}
used[i] = 1;
path.push_back(nums[i]);
getSets(nums,used,i+1);
path.pop_back();
used[i] = 0;
}
}
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<int> used(nums.size());
sort(nums.begin(),nums.end());
getSets(nums,used,0);
return res;
}
};
文章介绍了如何使用回溯算法解决LeetCode中的两个问题:93.复原IP地址,通过递归判断字符串是否合法并生成所有可能的IP组合;78.子集和90.子集II,涉及去重的子集问题,通过记录路径和使用used数组实现。
994

被折叠的 条评论
为什么被折叠?



