93.复原IP地址
题目链接: 93.复原IP地址
本题分割区间和 131.分割回文串 最大的不同是分割区间的判定:回文串是可以切割到最后,本题是不能切割到末尾,因为切割后就加上 “.
”,导致结尾有一个多余的 “.
”。因此终止条件也不能回文一样用startIndex
终止,终止条件使用pointSum
来判断,pointSum
表示插入 ".
"的个数。
直接在字符串s
上进行insert
、erase
“.
”,有两个好处:其一,无需在数字和string
间转换;其二,可以间接的处理了上述说的结尾问题。
对于区间的合法性判断,就像 131.分割回文串 对子串判断是否回文一样,额外定义一个判断函数,利于代码的可读性和逻辑。
class Solution {
vector<string> res;
void backtracking(string& s, int startIndex, int pointSum = 3) {
if (pointSum == 0) {
if (isValid(s, startIndex, s.size() - 1)) {//结尾和回文的区别
res.push_back(s);
return;
}
}
for (int i = startIndex; i < s.size(); ++i) {
if (isValid(s, startIndex, i)) {
s.insert(s.begin() + i + 1,'.');
--pointSum;
backtracking(s, i + 2/*startIndex多了一个1,是 . 的索引*/, pointSum);
s.erase(s.begin() + i + 1);
++pointSum;
} else break;//剪枝,有一个不满足,直接终止循环,而不是continue,执行下一个循环;
}
}
bool isValid(const string& s, int l, int r) {
if (r - l > 4) return false;//剪枝,且防止stoi溢出int
string tmpS = s.substr(l, r - l + 1);
if (!tmpS.empty()/*防止空字符引起的异常*/) {
int tmpV = stoi(tmpS);
int cnt = 1;
if (tmpV < 256) {
while (tmpV / 10) {
++cnt;
tmpV /= 10;
}
return cnt == tmpS.size();
}
}
return false;
}
public:
vector<string> restoreIpAddresses(string s) {
if (s.size()< 4 || s.size() > 12/*剪枝*/) return {};
backtracking(s, 0);
return res;
}
};
78.子集
题目链接:78.子集
收获结果的位置不同,不是以往的在终止条件收获结果。
class Solution {
vector<int> path;
vector<vector<int>> res;
void backtracking(vector<int>& nums, int startIndex) {
res.push_back(path);
if (startIndex == nums.size())
return;
for (int i = startIndex; i < nums.size(); ++i) {
path.push_back(nums[i]);
backtracking(nums, i + 1);
path.pop_back();
}
}
public:
vector<vector<int>> subsets(vector<int>& nums) {
backtracking(nums, 0);
return res;
}
};
终止条件可以去掉,因为for
循环的跳出条件也是startIndex == nums.size()
跳出循环,而for
函数体之后backtracking
函数体就结束了。
90.子集II
题目链接: 90.子集II
主要思路为78.子集和40.组合总和II
class Solution {
vector<int> path;
vector<vector<int>> res;
void backtracking(vector<int>& nums, int startIndex) {
res.push_back(path);
if (startIndex == nums.size()) return;
for (int i = startIndex; i < nums.size(); ++i) {
if (i > startIndex && nums[i] == nums[i - 1])
continue;
path.push_back(nums[i]);
backtracking(nums, i + 1);
path.pop_back();
}
}
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
backtracking(nums, 0);
return res;
}
};