力扣第93题 复原IP地址 c++ 回溯
题目
中等
相关标签
有效 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
中的任何数字。你可以按 任何 顺序返回答案。
示例 1:
输入:s = "25525511135" 输出:["255.255.11.135","255.255.111.35"]
示例 2:
输入:s = "0000" 输出:["0.0.0.0"]
示例 3:
输入:s = "101023" 输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]
提示:
1 <= s.length <= 20
s
仅由数字组成
题目解释
- 题目要求给定一个只包含数字的字符串,将其分割成 IPv4 地址的形式。要求返回所有可能的有效 IPv4 地址。
- IPv4 地址由4个用点分隔的数字组成,每个数字的取值范围是0到255。例如,字符串"25525511135"可以分割成"255.255.11.135"或"255.255.111.35"两种 IPv4 地址。
- 一个只包含数字的字符串
s
,通过在s
中插入 '.' 来形成有效的 IP 地址。有效的 IP 地址由四个整数组成,每个整数位于 0 到 255 之间,且不能含有前导 0。- 我们需要找出所有可能的有效 IP 地址,并按任意顺序返回结果。
思路和解题方法
- 将原始字符串按照一定规则(插入逗点)分割成四个子字符串。
- 判断每个子字符串是否是合法的 IP 地址段。
- 如果四个子字符串都合法,则将它们拼接起来并添加到结果集中。
具体实现中,
backtracking
函数通过遍历字符串的每个位置,在合适的位置插入逗点,并判断该分割是否合法。如果达到了分割成四个子字符串的条件,则判断最后一个子字符串是否合法,如果是,则将结果添加到结果集中。
isValid
函数用于判断一个子字符串是否合法,主要根据以下几个条件进行判断:
- 如果子字符串长度大于1且以0开头,则不合法。
- 如果子字符串包含非数字字符,则不合法。
- 将子字符串转换为整数,并判断是否大于 255。
最后,在
restoreIpAddresses
函数中,首先进行剪枝操作,判断给定字符串的长度是否在合法范围内(4 到 12 之间),如果不满足,则直接返回结果。然后调用backtracking
函数开始回溯过程,并返回最终结果。
复杂度
时间复杂度:
O(3^4)
时间复杂度: O(3^4),IP地址最多包含4个数字,每个数字最多有3种可能的分割方式,则搜索树的最大深度为4,每个节点最多有3个子节点。
空间复杂度
O(n)
空间复杂度: O(n)
c++ 代码
class Solution {
private:
vector<string> result; // 记录结果
// startIndex: 搜索的起始位置,pointNum: 添加逗点的数量
void backtracking(string& s, int startIndex, int pointNum) {
if (pointNum == 3) { // 逗点数量为3时,分隔结束
// 判断第四段子字符串是否合法,如果合法就放进result中
if (isValid(s, startIndex, s.size() - 1)) {
result.push_back(s);
}
return;
}
for (int i = startIndex; i < s.size(); i++) {
if (isValid(s, startIndex, i)) { // 判断 [startIndex, i] 这个区间的子串是否合法
s.insert(s.begin() + i + 1, '.'); // 在 i 的后面插入一个逗点
pointNum++;
backtracking(s, i + 2, pointNum); // 插入逗点之后下一个子串的起始位置为 i+2
pointNum--; // 回溯
s.erase(s.begin() + i + 1); // 回溯删掉逗点
} else {
break; // 不合法,直接结束本层循环
}
}
}
// 判断字符串 s 在左闭右闭区间 [start, end] 所组成的数字是否合法
bool isValid(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) {
result.clear();
if (s.size() < 4 || s.size() > 12) {
return result; // 算是剪枝了,如果字符串长度不在合法范围内,直接返回结果
}
backtracking(s, 0, 0);
return result;
}
};
觉得有用的话可以点点赞,支持一下。
如果愿意的话关注一下。会对你有更多的帮助。
每天都会不定时更新哦 >人< 。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)