1.题目描述
现在有一个只包含数字的字符串,将该字符串转化成IP地址的形式,返回所有可能的情况。
例如:
给出的字符串为"25525522135",
返回["255.255.22.135", "255.255.221.35"]. (顺序没有关系)
数据范围:字符串长度 0≤n≤120≤n≤12
要求:空间复杂度 O(n!)O(n!),时间复杂度 O(n!)O(n!)
注意:ip地址是由四段数字组成的数字序列,格式如 "x.x.x.x",其中 x 的范围应当是 [0,255]。
示例1
输入:
"25525522135"返回值:
["255.255.22.135","255.255.221.35"]示例2
输入:
"1111"返回值:
["1.1.1.1"]示例3
输入:
"000256"返回值:
[]
2.解题思路
回溯算法:先判断startIdx与当前访问到的结点i组成的子串 构成的数字是否符合题意,如果符合,就在i+1的位置处放置一个'.'分割该IP地址;然后从i+2的位置开始的子串就在下一次的递归中访问;如果本次递归中,'.'的个数已经为3个,且最后剩余部分对应的数字仍符合题意,就把当前s加入到答案中;回溯的过程:当前位置加入的'.'的后序所有序列都递归结束并返回结果时,需要进行一步撤销操作,把之前加入的'.'删除,再将i向右移动,继续判断新的位置对应的子串能否满足题意。
3.代码实现
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return string字符串ArrayList
*/
public ArrayList<String> res = new ArrayList<>();
public ArrayList<String> restoreIpAddresses (String s) {
// write code here
backTracking(s, 0, 0);
return res;
}
public void backTracking(String s, int startIdx, int pointNum) {
if (pointNum == 3) {
if (isValid(s, startIdx, s.length() - 1)) {
res.add(s);
return;
}
}
for (int i = startIdx; i < s.length(); i++) {
if (isValid(s, startIdx, i)) {
StringBuilder sb = new StringBuilder(s);
sb.insert(i + 1, ".");
backTracking(sb.toString(), i + 2, pointNum + 1);
s = sb.deleteCharAt(i + 1).toString();
} else {
return;
}
}
}
/**
* 判断当前子串对应数字是否合法 左闭右闭
* @param s
* @param start
* @param end
* @return
*/
public boolean isValid(String s, int start, int end) {
if (start >= s.length()) {
return false;
}
int firstIdx = -1;
//检查是否存在非数字字符
for (int i = start; i <= end; i++) {
char c = s.charAt(i);
if (!Character.isDigit(c)) {
return false;
}
if (firstIdx == -1 && c == '0') {
firstIdx = i;
}
}
//判断该子串对应数字是否在[0,255]区间内部
int x = Integer.parseInt(s.substring(start, end + 1));
if (x > 255 || x < 0) {
return false;
}
//判断当前子串对应数字是否包含前缀0
if (firstIdx == start && end > start) {
return false;
}
return true;
}
}