LeetCode 93.复原IP地址
题目链接:93.复原IP地址
踩坑:一开始是自己做的,踩了不少坑,纠结到底是切割几次,在想如果切割4次,该怎么让第4次固定切在结尾。但其实切3次即可。不知道string类的insert和erase函数。stoi函数的输入要有效(不为空,不超过int表示范围,不掺杂非法字符)
思路:与分割回文串类似,都属于切割问题,不同的是本题对切割的次数有限制。所以整体上就是对字符串进行切割,对切割出的字串进行合法性判断,如果合法,在其之后insert逗点。回溯时erase逗点。且在切割三次后,对尾部字串进行合法性判断,若合法,则收集。
代码:这是我自己提交的代码,可能有点混乱,建议看卡哥的。
class Solution {
public:
void backtracking(string& s, int start, int count, string& path, vector<string>& result)
{
if(count == 4)
{
if(isip(s, start, s.length()-1))
{
string t = path;
path = path + s.substr(start, s.length()-start);
result.push_back(path);
path = t;
}
return;
}
for(int i = start; i < s.length() && i < start + 3; i++)
{
string t = path;
if(isip(s, start, i))
{
path = path + (s.substr(start, i-start+1) + ".");
}
else continue;
backtracking(s, i+1, count+1, path, result);
path = t;
}
}
bool isip(string& s, int left, int right)
{
string t = s.substr(left, right-left+1);
if(t.length()==0 || t.length() > 3) return false;
int a = stoi(t);
if(t[0] == '0' && t.length() != 1) return false;
if(a >=0 && a <= 255) return true;
else return false;
}
vector<string> restoreIpAddresses(string s) {
vector<string> result;
string path;
backtracking(s, 0, 1, path, result);
return result;
}
};
LeetCode 78.子集
题目链接:78.子集
踩坑:哈哈哈哈昨天在做切割问题的时候就已经思考到求子集了,所以没任何坑。
思路:本题有助于我们理解回溯的整体过程。回溯的过程其实就是对所有子集的遍历,之前的题目只是在遍历到特定的子集时巧妙地运用它,而这里只需要收集。
代码:
class Solution {
public:
void backtracking(vector<int>& nums, int start, vector<int>& path, vector<vector<int>>& result)
{
result.push_back(path);
for(int i = start; i < nums.size(); i++)
{
path.push_back(nums[i]);
backtracking(nums, i+1, path, result);
path.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
vector<int> path;
vector<vector<int>> result;
backtracking(nums, 0, path, result);
return result;
}
};
LeetCode 90.子集II
题目链接:90.子集II
踩坑:忘记sort了。。。
思路:在之前的组合总和问题中已经把去重玩明白了,核心就是前一个元素不在路径中说明在回溯(树层),在路径中说明在递归(树枝),只要保证在横向遍历时不要选到重复元素即可。
代码:
class Solution {
public:
void backtracking(vector<int>& nums, vector<int> used, int start, vector<int>& path, vector<vector<int>>& result)
{
result.push_back(path);
for(int i = start; i < nums.size(); i++)
{
if(i > 0 && nums[i] == nums[i-1] && used[i-1] == 0) continue;
path.push_back(nums[i]);
used[i] = 1;
backtracking(nums, used, i+1, path, result);
path.pop_back();
used[i] = 0;
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<int> used(nums.size(), 0);
vector<int> path;
vector<vector<int>> result;
sort(nums.begin(), nums.end());
backtracking(nums, used, 0, path, result);
return result;
}
};