描述
现在有一个只包含数字的字符串,将该字符串转化成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"
返回值:
[]
求解思路
使用递归的思想,把数字字符串进行分割,然后在分割的基础上面继续分割,如果遇到不符合IP地址的格式,则这一“分支”的递归就结束,然后再看其他分割的结果。
其中参考杭电 De梦的终止条件和段位合法性,我们有:当IP地址的点的数量达到3个时,停止递归。对于段位的合法性,可以参考方法一的暴力法求解,即不能出现格式不符合IP地址的数字组合。
import java.util.ArrayList;
public class Solution {
public ArrayList<String> restoreIpAddresses(String s) {
ArrayList<String> res = new ArrayList<>();
ArrayList<String> ip = new ArrayList<>(); //存放中间结果
dfs(s, res, ip, 0);
return res;
}
private void dfs(String s, ArrayList<String> res, ArrayList<String> ip, int start){
if(ip.size() == 4 && start == s.length()){ //找到一个合法解
res.add(ip.get(0) + '.' + ip.get(1) + '.' + ip.get(2) + '.' + ip.get(3));
return;
}
if(s.length() - start > 3 * (4 - ip.size())) //剪枝
return;
if(s.length() - start < (4 - ip.size())) //剪枝
return;
int num = 0;
for(int i = start; i < start + 3 && i < s.length(); i++){
num = num * 10 + (s.charAt(i) - '0');
if(num < 0 || num > 255) //剪枝
continue;
ip.add(s.substring(start, i + 1));
dfs(s, res, ip, i + 1);
ip.remove(ip.size() - 1);
if(num == 0) //不允许前缀0
break;
}
}
}
复杂度分析
时间复杂度:递归所消耗的时间,为O
空间复杂度:递归使用的空间,O(N)