有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。
例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。
给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你不能重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/restore-ip-addresses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
输入:s = "25525511135" 输出:["255.255.11.135","255.255.111.35"]
思路:剪枝条件
假设此时字符串为"123313"
因为我们要剪成四段,假设先每段剪一个单位,
第一段为 "1",第二段为"2",第三段为"3",第四段长度为"3",
此时还剩余未剪的字符串"13",所以这种裁剪方法不行。
我们将最后一段的操作撤销,让它裁剪单位为2,第四段为"31",
此时还剩余未剪的字符串"3",所以这种裁剪方法也不行。
我们再次将最后一段的操作撤销,让它裁剪单位为3,第四段为"313",
此时未剩余未剪的字符串,将此次裁剪结果加入最终数组中。
此时,撤销最后两次裁剪,让第三段裁剪单位为2,第三段为"33",第四段裁剪单位为1,第四段为"1",此时还剩余未剪的字符串"13",所以这种裁剪方法不行。
我们再次撤销最后一次裁剪,第四段裁剪单位为2,第四段为"13",
此时未剩余未剪的字符串,将此次裁剪结果加入最终数组中。
之后依次撤销裁剪操作,将符合条件的结果加入最终数组返回即可。
代码:
class Solution {
List<String> res = new ArrayList<>();
Deque<String> path = new ArrayDeque<>(4);
String s;
public List<String> restoreIpAddresses(String s) {
this.s = s;
dfs(0, 4);
return res;
}
//begin开始遍历的位置,reside剩余的段数
public void dfs(int begin, int reside){
//当剩余段数为 0 且遍历到最后一个字符时,将此时的path添加到结果中
if(reside == 0){
if(begin == s.length()){
res.add(String.join(".", path));
}
return;
}
//最多截取三个数
for(int i=begin; i<begin+3; i++){
if(i >= s.length())
break;
//字符串剩余长度和分段所需长度
if(s.length()-i > reside*3)
continue;
if(judgeNumber(s, begin, i)){
String curS = s.substring(begin, i+1);
path.addLast(curS);
dfs(i+1, reside-1);
path.removeLast();
}
}
}
//判断是否符合不含有前导 0 以及是否在 0 ~ 255
public boolean judgeNumber(String s, int left, int right){
int len = right - left + 1;
if(len>1 && s.charAt(left)=='0')
return false;
int resLen = len<=0 ? 0 : Integer.parseInt(s.substring(left, right+1));
return resLen>=0 && resLen<=255;
}
}