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
中的任何数字。你可以按 任何 顺序返回答案。
示例 1:
cpp
输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]
示例 2:
cpp
输入:s = "0000"
输出:["0.0.0.0"]
示例 3:
cpp
输入: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
仅由数字组成
思路分析:
回溯法,对字符串进行切割,每一次切割我们都对他进行合法性检查,如果合法就在原来的字符串基础上加上 '.'。
当然我们需要一个变量 commanum 来记录 '.' 出现的次数(合法的 ip 地址有三个 '.' )。
递归的结束条件 , 当 commanum==3,说明当前的字符串已经被分割成了 4 段 。
此时我们判断 第4 段如果是合法的 ,那么就进行收集 。不管合不合法 我们都会进行返回。
cpp
if( commanum == 3 ){
if( islegal(s ,index ,s.length()-1) ){
ret.push_back(s);
}
return ;
}
合法性检查:左闭右闭的区间
cpp
//判断是否合法ip ,每一段
bool islegal(string &s ,int left ,int right){
//1. 先判断 011 这个情况
if(left > right) return false;
if(s[left] == '0' && left!=right) return false;
int value = 0;
while(left<=right){ //收集每一段的和
value=value*10 + (s[left] - '0');
left++;
}
if(value > 255 ) return false;
return true;
}
处理逻辑:index->记录切割的起始位置 。 commanum - > 记录'.' 的个数。
void backtraking(string &s , int index ,int &commanum)
回溯过程 : 去掉一个加入的 '.' , 并且commanum 减 1。
具体代码实现
cpp
class Solution {
public:
//判断是否合法ip ,每一段
bool islegal(string &s ,int left ,int right){
//1. 先判断 011 这个情况
if(left > right) return false;
if(s[left] == '0' && left!=right) return false;
int value = 0;
while(left<=right){
value=value*10 + (s[left] - '0');
left++;
}
if(value > 255 ) return false;
return true;
}
//commanum · 的个数
void backtraking(string &s , int index ,int &commanum){
if( commanum == 3 ){
//判断最后一段是否合法
//[index ,s.length()-1)]
if( islegal(s ,index ,s.length()-1) ){
ret.push_back(s);
}
return ;
}
for( int i = index ;i < s.length() ; i++ ){
if(islegal(s , index , i )){ //如果合法就加上 .
//[index , i] 这个区间的字串
s.insert( s.begin()+i+1 , '.' );
commanum++;
/*
这里是i+2 ,因为我们加入了一个 '.' ,所以要在i+1的基础上 +1
*/
backtraking(s , i + 2 ,commanum);
//回溯-> 去掉一个 .
s.erase( s.begin() + i + 1 );
commanum--;
}else{ // 不合法就结束本层循环
break;
}
}
}
vector<string> restoreIpAddresses(string s) {
//如果传入的字符串为空 ,或者大于12 小于4 都是不合法的
if(s.length() == 0 || s.length() > 12 || s.length() < 4) return ret;
backtraking(s ,0 ,commanum);
return ret;
}
private:
vector<string>ret; // 收集结果集
int commanum = 0; //记录 '.' 的个数
};
希望对你有所帮助。