题目:有效ip
地址由四位整数组成,整数之间用.
进行分割。现给定一个只包含数字的字符串s
,表示一个ip
地址,要求返回所有可能的IP
地址。
输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]
解题思路
如果第一次做此类题目,可能会有点懵,我建议你可以先做一下 131和132的分割回文串,或者先看我上一篇文章。本题和分割回文串还是很相似的,分割回文串是对字符串进行分割,分割过程中没有限定分割次数,每次判断分割的字符串是否为回文即可。而本题也是对字符串进行分割,只不过限定了分割次数为3
,并且分割后需要对分割后的字符串判断是否越界255
。
那根据分割回文串的思路,我们还是从起始索引进行分割,每次分割进行数值判断,满足条件则加入结果集合,本题的 结束点是结果集的大小为4
,并且此时我们已经到达字符串末尾 。根据此思路可得代码:
private List<String> result3 = new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
if(s.length()>12) return result3;
backtrace3(s, 0, new ArrayList<>());
System.out.println(result3);
return result3;
}
public void backtrace3(String s, int cur, ArrayList<String> temp){
if(temp.size() == 4 && cur == s.length()) {
StringBuilder sb = new StringBuilder();
for (String s1 : temp) {
sb.append(s1);
sb.append(".");
}
sb.deleteCharAt(sb.length()-1);
result3.add(sb.toString());
return;
}
for(int i=cur;i<s.length();i++){
String sub = s.substring(cur, i + 1);
if(sub.length()>3||Integer.parseInt(sub)>255||(sub.length()>1&&sub.charAt(0)=='0')){
continue;
}
temp.add(sub);
backtrace3(s, i+1, temp);
temp.remove(temp.size()-1);
}
}
实际上本题还可以进行扩展,因为题目限定输入的所有字符串只包含数字,那假设我们输入的字符串可以包含除数字之外的特殊字符呢?包含特殊字符的字符串必定是不满足的,也即我们可以在起始点先循环一次字符串,当包含除数字之外的字符时直接返回空列表。
在此基础上还能进一步扩展,当输入字符串不仅包含特殊字符,还要求将特殊字符进行替换,并且所有相同的特殊字符只能替换成相同的数字,返回最终的结果。又该如何?
我的思路是先将特殊字符加入结果集,在结果集大小为4
的时候,我们需要对结果集中的所有字符串进行判断,如果包含特殊字符,就将特殊字符以0-9
之间的数字进行替换,依次循环替换,找到所有满足条件的,着其中涉及了很多for
循环,我觉得并不是一个好的思路。
我还有一个思路是在回溯之前就将字符串循环一次,使用map保存所有特殊字符和它的位置,之后直接判断替换后的所有字符串,这可能是较为简单的方法了。在此简单的列一下思路,并不完善:
public List<String> restoreIpAddresses2(String s) {
if(s.length()>12) return result3;
HashSet<Character> set = new HashSet<>();
for(int i=0;i<s.length();i++){
if(s.charAt(i)>'9'||s.charAt(i)<'0'){
set.add(s.charAt(i));
}
}
ArrayList<String> str_list = new ArrayList<>();
if(!set.isEmpty()){
for(int i=0;i<=9;i++){
for (Character c : set) {
s.replace(c, (char) i);
str_list.add(s);
}
}
}
if(!str_list.isEmpty()){
for (String s1 : str_list) {
backtrace3(s1, 0, new ArrayList<>());
}
}
backtrace3(s, 0, new ArrayList<>());
System.out.println(result3);
return result3;
}