问题:
Given a string containing only digits, restore it by returning all possible valid IP address combinations.
For example:
Given "25525511135"
,
return ["255.255.11.135", "255.255.111.35"]
. (Order does not matter)
解决:http://www.cnblogs.com/grandyang/p/4305572.html
【经验】一是只要遇到字符串的子序列或配准问题首先考虑动态规划DP,二是只要遇到需要求出所有可能情况首先考虑用递归。
① 这道题并非是求字符串的子序列或配准问题,更符合第二种情况,所以我们要用递归来解。我们用k来表示当前还需要分的段数,如果k = 0,则表示三个点已经加入完成,四段已经形成,若这时字符串刚好为空,则将当前分好的结果保存。若k != 0, 则对于每一段,我们分别用一位,两位,三位来尝试,分别判断其合不合法,如果合法,则调用递归继续分剩下的字符串,最终求出所有合法组合。
class Solution { //5ms
public List<String> restoreIpAddresses(String s) {
List<String> res = new ArrayList<>();
dfs(s,0,"",res);
return res;
}
public void dfs(String s,int i,String out,List<String> res){
if(i == 4){
if(s.isEmpty()) res.add(out);
return;
}
for(int k = 1;k <= 3;k ++){
if(s.length() < k) break;
int val = Integer.parseInt(s.substring(0,k));
if(val > 255 || k != String.valueOf(val).length()) continue;
dfs(s.substring(k),i + 1,out + s.substring(0,k) + (i == 3 ? "" : "."),res);
}
}
}
② 在discuss中看到的,使用递归的方法。
class Solution {//2ms
public List<String> restoreIpAddresses(String s) {
List<String> res = new ArrayList<String>();
if (s.length() > 12 || s.length() < 4){
return res;
}
dfs(s,0,4,"",res);
return res;
}
public void dfs(String s,int i,int k,String out,List<String> res){
if(s.length() - i > 3 * k || s.length() - i < k){
return;
}
if(k == 0){
res.add(new String(out));
return;
}
int num = 0;
int count = 0;
for (int j = i;j < s.length() ;j ++ ) {
char c = s.charAt(j);
num = num * 10 + c - '0';
count ++;
out += c;
if(num > 255 || (count > 1 && num < 10)){//不符合IP地址的定义
break;
}
if(k > 1){
dfs(s,j + 1,k - 1,out + '.',res);
}else{
dfs(s,j + 1,k - 1,out,res);
}
}
}
}
③ 这里IP的特性是最大数字不能超过255。比上个方法好的地方在于a+b+c+d= s.length()才会判断数字是否合法,避免了很多1+1+1+N这种不需要检查的情况。
class Solution { //4ms
public List<String> restoreIpAddresses(String s) {
List<String> res = new ArrayList<String>();
int len = s.length();
for (int i = 1; i <= 3;i ++){ //第一段
if (len - i > 9) continue;
for (int j = i + 1; j <= i + 3;j ++){ //第二段
if (len - j > 6) continue;
for (int k = j + 1; k <= j + 3 && k < len;k ++){ //第三段
int a,b,c,d; // 将四段使用"."分割
a = Integer.parseInt(s.substring(0,i));
b = Integer.parseInt(s.substring(i,j));
c = Integer.parseInt(s.substring(j,k));
d = Integer.parseInt(s.substring(k));
if (a > 255 || b > 255 || c > 255 || d > 255) continue;
String ip = a + "." + b + "." + c + "." + d;
if (ip.length() < len + 3 ) continue; // 像“01”这样的要单独处理
res.add(ip);
}
}
}
return res;
}
}