93. 复原 IP 地址
「这是我参与2022首次更文挑战的第23天,活动详情查看:2022首次更文挑战」。
难度:mid 来源:力扣(LeetCode)
有效 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 = "1111" 输出:["1.1.1.1"]
示例 4:
输入:s = "010010" 输出:["0.10.0.10","0.100.1.0"]
示例 5:
输入:s = "101023" 输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]
提示:
- 0 <= s.length <= 20
- s 仅由数字组成
思路:
该题目也属于字符串分割问题,最好可以先看一下lc131:分割回文串;大体思路需要两个变量:
index实现字符串的分割,pointNum实现判断点的数量;
通过上述两个变量可以实现结束条件:
- 判断逗号的数量
- 判断时候满足ip地址的要求
对于第一个要求,只需要判断pointNum是否等3,如果等于3则判断最后一组是否满足要求,满足要求则添加入结果中,否则break;
根据题目知第二个要求为:
- 每个整数不能以0开头
- 每个整数范围0-255
- 存在非整数是非法的
由上得:
//如果小数点等于三,表示前三个满足提议
if(pointNum == 3){
//判断最后一组是否满足要求
if(isValid(s,index,s.length()-1)){
res.add(s);
return;
}
}
Boolean isValid(String s,int start,int end){
if(start > end) return false;
// 1. 每个整数不能以0开头
// 2. 每个整数范围0-255
// 3. 存在非整数是非法的
int num = 0;
if(s.charAt(start) == '0' && start != end) return false;
for(int i = start; i <= end; i++){
if(s.charAt(i) < '0' || s.charAt(i) > '9') return false;
num = num * 10 + (s.charAt(i) - '0');
if (num > 255) { // 如果⼤于255了不合法
return false;
}
}
return true;
}
然后进行字符串的横向遍历,如果有满足条件的(该题目在原来的字符串上进行修改):
- 在满足条件的位置上添加上逗号
- pointNum++
- 递归
- pointNum--
- 回溯
for(int i = index; i < s.length(); i++){
//如果满足条件
if (isValid(s, index, i)) {
//找到的位置进行分割,中间加入点
s = s.substring(0,i+1) + "." +s.substring(i+1);
pointNum++;
backTrack(s,i+2,pointNum);
pointNum--;
// i+1的位置为点----5 . 5
//-----------------i i+1 i+2
s = s.substring(0,i+1)+s.substring(i+2);
}else{
break;
}
}
简单的优化:根据题目可以需要满足IP要求。
字符串的长度小于 4 或者大于 12 ,一定不能拼凑出合法的 ip 地址
小于4拼不出0.0.0.0,最多255.255.255.255也就是在原字符串长度12,其他都不符合
完整代码:
class Solution {
List<String> res = new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
//index: 切割点,pointNum:小数点
// 字符串的长度小于 4 或者大于 12 ,一定不能拼凑出合法的 ip 地址
//小于4拼不出0.0.0.0,最多255.255.255.255也就是长度12,其他都不符合
if(s.length() < 4 || s.length() > 12) return res;
backTrack(s,0,0);
return res;
}
void backTrack(String s,int index,int pointNum){
//如果小数点等于三,表示前三个满足提议
if(pointNum == 3){
//判断最后一组是否满足要求
if(isValid(s,index,s.length()-1)){
res.add(s);
return;
}
}
for(int i = index; i < s.length(); i++){
//如果满足条件
if (isValid(s, index, i)) {
//找到的位置进行分割,中间加入点
s = s.substring(0,i+1) + "." +s.substring(i+1);
pointNum++;
backTrack(s,i+2,pointNum);
pointNum--;
// i+1的位置为点----5 . 5
//-----------------i i+1 i+2
s = s.substring(0,i+1)+s.substring(i+2);
}else{
break;
}
}
}
Boolean isValid(String s,int start,int end){
if(start > end) return false;
// 1. 每个整数不能以0开头
// 2. 每个整数范围0-255
// 3. 存在非整数是非法的
int num = 0;
if(s.charAt(start) == '0' && start != end) return false;
for(int i = start; i <= end; i++){
if(s.charAt(i) < '0' || s.charAt(i) > '9') return false;
num = num * 10 + (s.charAt(i) - '0');
if (num > 255) { // 如果⼤于255了不合法
return false;
}
}
return true;
}
}