链接:
https://leetcode.com/problems/restore-ip-addresses/
大意:
给定一个只由数字组成的字符串s,要求出其可能的所有的ip地址形式。例子:
思路:
回溯+剪枝。
主要思路就是找ip地址的三个点在s中的位置。
设置一个列表idxs存储三个点的位置,当字符串s的长度大于 3 * (4 - idxs.size()) 或者 小于1 * (4 - idxs.size()) 时,直接退出,表示不满足ip的形式(每一级ip的长度为1,2或3)
当idxs的大小size达到了3时,表明3个点已经找到了(且对于每个点的左边部分都是满足ip形式的),此时需验证第四部分是否满足ip的规则。如果第四部分的为0开头且不仅一位数字或者第四部分的数字大于255,则直接返回。否则在原来字符串对应位置加上'.'使其成为ip
详情看代码。
代码:
// 找三个点的位置 可以有两个连续的0吗? 不可以有两个连续的0 0不能开头
class Solution {
public List<String> restoreIpAddresses(String s) {
List<String> res = new ArrayList<>();
// 提前判断不符合条件的情况
if (s.length() < 4 || s.length() > 12)
return res;
LinkedList<Integer> idxs = new LinkedList<>();
dfs(s, idxs, 0, res, s); // index初始为0
return res;
}
// index为上一个点在原字符串(不是子串)的位置
public void dfs (String s, LinkedList<Integer> idxs, int index, List<String> res, String sAll) {
// 长度不满足要求 直接退出
if (s.length() > 3 * (4 - idxs.size()) || s.length() < 1 * (4 - idxs.size()))
return ;
// 找到一种可能的ip
if (idxs.size() == 3) {
// 最后一段不满足ip地址的要求
if (s.charAt(0) == '0' && s.length() > 1 || Integer.parseInt(s) > 255)
return ;
StringBuilder sb = new StringBuilder();
int i = 0, pos = 0;
//System.out.println(Arrays.toString(idxs.toArray()));
while (i < sAll.length()) {
if (pos < idxs.size() && i == idxs.get(pos)) {
sb.append(".");
pos++;
}
sb.append(sAll.charAt(i));
i++;
}
res.add(sb.toString());
return ;
}
int j = 0, num = 0;
while (j < 3 && j < s.length()) {
num = num * 10 + s.charAt(j) - '0';
if(num == 0) { // num == 0时0只能作为ip的某一级,即不能和其他数字组合
idxs.addLast(index + j + 1);
dfs(s.substring(j + 1), idxs, index + j + 1, res, sAll);
idxs.removeLast();
return ;
}
if (num <= 255) {
idxs.addLast(index + j + 1);
dfs(s.substring(j + 1), idxs, index + j + 1, res, sAll);
idxs.removeLast();
}
j++;
}
}
}
结果:
结论:
很有意思的一个回溯题。