問題
給定一個只包含數字的字符串,返回所有有效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;
}
}