题目链接:leetcode 93.复原IP地址
文章讲解:代码随想录 93.复原IP地址讲解
视频讲解:回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址
思路和解法
题目:
有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。
例如:“0.1.2.201” 和 “192.168.1.1” 是 有效 IP 地址,但是 “0.011.255.245”、“192.168.1.312” 和 “192.168@1.1” 是 无效 IP 地址。
给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 ‘.’ 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。
想法:
要注意的很多,都在注释中。
class Solution {
public:
//存结果
vector<string> result;
//不需要path
//后补上的isValid函数
bool isValid(string& s, int startIndex, int endIndex) {
//这里不加会导致最后一段是空的结果
if (startIndex > endIndex) {
return false;
}
//一共有几种失效的情况 1、0开头的数字 2、超过255 3、非正常数字
if (s[startIndex] == '0' && startIndex != endIndex) {
return false;
}
//遍历每个数字 转换成数字 便于判断是否超过255 同时可以判断数字是否正常
//记录当前段的数字
int num = 0;
for (int i = startIndex; i <= endIndex; i++) {
if (s[i] < '0' || s[i] > '9') {
return false;
}
num = num * 10 + (s[i] - '0');
if (num > 255) {
return false;
}
}
return true;
}
//递归+回溯
//分割区间[startIndex, i] 终止条件需要记录pointNum
//这里加&会怎么样
void backTracking(string& s, int startIndex, int pointNum) {
//终止条件 isValid
if (pointNum == 3 && isValid(s, startIndex, s.size() - 1)) {
result.push_back(s);
return ;
}
//递归处理逻辑
for (int i = startIndex; i < s.size(); i++) {
//如果当前分割字段有效 需要向下递归+回溯
if (isValid(s, startIndex, i)) {
//插入'.' 这里犯了第一个错误 insert输入参数应该是迭代器
s.insert(s.begin() + i + 1, '.');
pointNum++;
//向下递归 注意此时已经加入了'.',所以要注意startIndex的位置
backTracking(s, i + 2, pointNum);
//回溯
pointNum--;
//这里犯了同样错误 应该用迭代器
s.erase(s.begin() + i + 1);
} else break;//这里自己写的没加break
}
return ;
}
vector<string> restoreIpAddresses(string s) {
result.clear();
//这里剪枝自己没想到
if (s.size() < 4 || s.size() > 12) return result;
//如果第三个参数写成引用 这里还不能传0
backTracking(s, 0, 0);
return result;
}
};
题目链接:leetcode 78.子集
文章讲解:代码随想录 78.子集讲解
视频讲解:回溯算法解决子集问题,树上节点都是目标集和! | LeetCode:78.子集
思路和解法
题目:
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
想法:
很简单。
class Solution {
public:
//需要记录路径上所有结果 所以需要path
vector<int> path;
vector<vector<int>> result;
//递归函数
void backTracking(vector<int>& nums, int startIndex) {
//终止条件
result.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();
}
return ;
}
vector<vector<int>> subsets(vector<int>& nums) {
result.clear();
path.clear();
backTracking(nums, 0);
return result;
}
};
题目链接:leetcode 90.子集II
文章讲解:代码随想录 90.子集II讲解
视频讲解:回溯算法解决子集问题,如何去重?| LeetCode:90.子集II
思路和解法
题目:
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
想法:
很简单。自己写都AC了。
class Solution {
public:
//提供的数组中有重复元素 所以需要去重 所以要排序
vector<int> path;
vector<vector<int>> result;
//递归函数
void backTracking(vector<int>& nums, int startIndex) {
//收集结果
result.push_back(path);
//终止条件
if (startIndex >= nums.size()) return ;
//递归处理逻辑 注意这里都是假设nums已经排完序了
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();
}
return ;
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
path.clear();
result.clear();
sort(nums.begin(), nums.end());
backTracking(nums, 0);
return result;
}
};