问题
给定一个只包含数字的字符串,返回所有有效IP地址的组合。
输入:"25525511135"
输出:["255.255.11.135", "255.255.111.35"]
解析
首先字符串只可能切成四份,每一份都必须是有效的IP段位,即0~255。第一种解法,暴力求解,三重循环:第一层循环判断第一个段位是否有效且后续字符串的长度是否大于9(后续三个段位长度最大就是9),是进行下一次循环;后续的类似,直到最终所有的段位都有效且字符串长度分配完毕。
判断段位有效的条件:0~255之间 && 如果长度大于1,则不能以0开头。
还有类似问题的通用解法:回溯。
两个解法的时间复杂度(1ms)和空间复杂度(38M)接近。
Java 代码
回溯法:
class Solution {
List<String> output;
public void restoreIpAddresses(String s, int index, StringBuilder sb, int count) {
if(count > 4 || (count == 4 && s.length() != index)) {
return;
}
if(s.length() == index) {
if(count == 4) {
output.add(sb.substring(0,sb.length()-1));
}
return;
}
if(s.charAt(index) == '0') {
sb.append(s.charAt(index));
sb.append(".");
restoreIpAddresses(s,index+1,sb,count+1);
sb.deleteCharAt(sb.length()-1);
sb.deleteCharAt(sb.length()-1);
}else{
if(s.length() >= index+1) {
sb.append(s.charAt(index));
sb.append(".");
restoreIpAddresses(s,index+1,sb,count+1);
sb.deleteCharAt(sb.length()-1);
sb.deleteCharAt(sb.length()-1);
}
if(s.length() >= index+2) {
sb.append(s.charAt(index));
sb.append(s.charAt(index+1));
sb.append(".");
restoreIpAddresses(s,index+2,sb,count+1);
sb.deleteCharAt(sb.length()-1);
sb.deleteCharAt(sb.length()-1);
sb.deleteCharAt(sb.length()-1);
}
if(s.length() >= index+3) {
int n = Integer.parseInt(s.substring(index,index+3));
if(n <= 255) {
sb.append(s.charAt(index));
sb.append(s.charAt(index+1));
sb.append(s.charAt(index+2));
sb.append(".");
restoreIpAddresses(s,index+3,sb,count+1);
sb.deleteCharAt(sb.length()-1);
sb.deleteCharAt(sb.length()-1);
sb.deleteCharAt(sb.length()-1);
sb.deleteCharAt(sb.length()-1);
}
}
}
}
public List<String> restoreIpAddresses(String s) {
output = new ArrayList<>();
restoreIpAddresses(s , 0, new StringBuilder(), 0);
return output;
}
}
三重循环法:
class Solution {
public List<String> restoreIpAddresses(String s) {
List<String> out = new ArrayList<>();
for (int i = 0; i <= 3 && i < s.length(); i++) {
String part1 = s.substring(0, i);
if (!isValid(part1)||s.length()-i-1>9)
continue;
for (int j = i + 1; j <= i + 3 && j < s.length(); j++) {
String part2 = s.substring(i, j);
if (!isValid(part2)||s.length()-j-1>6)
continue;
for (int k = j + 1; k <= k + 3 && k < s.length(); k++) {
String part3 = s.substring(j, k);
String part4 = s.substring(k);
if (!isValid(part3) || !isValid(part4))
continue;
StringBuilder sb = new StringBuilder();
sb.append(part1);
sb.append(".");
sb.append(part2);
sb.append(".");
sb.append(part3);
sb.append(".");
sb.append(part4);
out.add(sb.toString());
}
}
}
return out;
}
static boolean isValid(String s) {
return s.length() > 0 && !(s.length() > 1 && s.startsWith("0")) && !(s.length() > 3) && Integer.valueOf(s) <= 255;
}
}