Leetcode: 93 复原IP地址
可以将其类比于分割回文串的题型。
基本思路
- 输入:除了继续分割点位的idx,还需要count来记录'.'的数量,当等于3的时候,判断最后一段是不是有效数字就可以了。
- 终止条件:count等于3
- 基本逻辑:每次分割之后,需要判断是不是符合规则。
主要困难点在于判断是否合法
- 段位以0为开头的数字不合法
- 段位里有非正整数字符不合法
- 段位如果大于255了不合法
class Solution {
private:
vector<string> result;
void traceback(string s, int idx, int count){
if(count == 3){//终止条件
if(isvaid(s, idx, s.size() - 1))//判断最后一段是否合法
return result.push_back(s);
}
for(int i = idx; i < s.size(); i++){
if(isvaid(s, idx, i)){
s.insert(s.begin() + i + 1 , '.'); // 在i的后面插入一个逗点
count++;
traceback(s,i + 2, count);//i+2是因为加上了逗点
count--;
s.erase(s.begin() + i + 1);//回溯记得删掉
}
}
}
// 判断字符串s在左闭又闭区间[start, end]所组成的数字是否合法
bool isvaid(const string& s, int start, int end) {
if (start > end) {
return false;
}
if (s[start] == '0' && start != end) { // 0开头的数字不合法
return false;
}
int num = 0;
for (int i = start; i <= end; i++) {
if (s[i] > '9' || s[i] < '0') { // 遇到非数字字符不合法
return false;
}
num = num * 10 + (s[i] - '0');
if (num > 255) { // 如果大于255了不合法
return false;
}
}
return true;
}
public:
vector<string> restoreIpAddresses(string s) {
traceback(s, 0, 0);
return result;
}
};
Leetcode: 78 子集
这道题起始比之前的组合题目都要简单,只要把所有的路径情况记录下来就好,但是一些要点很容易忽略。
- 终止条件:需要定义一个startidx来指向当前回溯的位置,终止条件是指向最末尾的时候结束。或者可以不加终止条件,因为我们本来就要遍历整棵树。
- 收集result要放在终止条件前面,不然本身的情况就记录不到了。
代码如下,是非常传统的模板
时间复杂度: O(n * 2^n)
空间复杂度: O(n)
class Solution {
private:
vector<vector<int>> result;
vector<int> vec;
void traceback(vector<int>& nums, int idx){
result.push_back(vec);
if(idx >= nums.size()){
return;
}
for(int i = idx; i < nums.size(); i++){
vec.push_back(nums[i]);
traceback(nums, i + 1);//向下一层递归
vec.pop_back();
}
}
public:
vector<vector<int>> subsets(vector<int>& nums) {
traceback(nums, 0);
return result;
}
};
Leetcode: 90 子集II
本题就是上一题叫上去重的操作。也是非常简单的。就是遍历全部节点+去重(可以作为一个模板记忆)
容易出错的地方,就是容易忘记对之前的数组先进行排序。
class Solution {
private:
vector<vector<int>> result;
vector<int> vec;
void traceback(vector<int>& nums, int idx){
result.push_back(vec);
if(idx >= nums.size()){
return;
}
for(int i = idx; i < nums.size(); i++){
if (i > idx && nums[i] == nums[i - 1] ) {
continue;
}
vec.push_back(nums[i]);
traceback(nums, i + 1);//向下一层递归
vec.pop_back();
}
}
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(),nums.end());
traceback(nums, 0);
return result;
}
};