- 主函数里,统计字符串的长度len,建立结果集res,路径集合path,判断一下len的长度是否满足要求即 若大于12 或者小于4,则直接返回res,因为这是不符合规范的
- 在回溯函数中,首先设定终止条件:当begin开始位置和长度一样的时候,并且剩余字段residue也是0,则将path加入到res中并且前面还要,加上’.'号
- 当i < begin + 3的时候,若i >= len 则直接break。当剩余字段个数*3 < len - i 的时候,说明不满足条件,至少应该大于或者等于
- 然后判断是否是合法的地址,若是,则进行截取,然后加入到path中,然后进入下一层的回溯函数,进入回溯函数的时候,begin的位置应该是 i+1,而不是begin+ 1,此外residue - 1,最后移除
- 判断IP地址合法的函数:首先统计传入的字符串的长度len,然后当 len>1 并且第一个位置是0的时候,返回false
- 定义res保存结果,最后返回res是否在0-255之间,即[0,255]
- 二刷:在截止条件处,不管residue是否为0,都要执行 return,因为此时的 begin 已经是 len 了,说明已经到头了
- 在递归到下一层的时候,begin的位置是 i + 1,剩余字段的个数 residue - 1
- 在判断是否是满足 0-255 之间的函数中,需要在len > 1 的时候判断第一个位置是否是 0,因为len 的计算是通过,right - left + 1,来实现的,因为right 和 left 不可能相等,则结果至少大于1。 在最后的返回结果出,要返回是否 0 <= res <= 255 要注意等号
- 在for循环中 if(i >= len)则break 而 if(len - i > residue * 3) 执行的是 continue
- 在判断是否回文的函数中,计算res 时, res = res * 10 + s.charAt(left) - '0’
class Solution {
List<String> res = new ArrayList<>();
Deque<String> path = new ArrayDeque<>();
public List<String> restoreIpAddresses(String s) {
int len = s.length();
if(len < 4 || len > 12) return res;
dfs(s, len, 0, 4);
return res;
}
public void dfs(String s, int len, int begin, int residue){
//截止条件
if(begin == len){
if(residue == 0){
res.add(String.join(".", path));
}
return;
}
for(int i = begin; i < begin + 3; i++){
if(i >= len) break;
if(len - i > residue * 3) continue;
if(judgeIpSegment(s, begin, i)){
String str = s.substring(begin, i + 1);
path.addLast(str);
dfs(s, len, i + 1, residue - 1);
path.removeLast();
}
}
}
public boolean judgeIpSegment(String s, int left, int right){
int len = right - left + 1;
if(len > 1 && s.charAt(left) == '0') return false;
int res = 0;
while(left <= right){
res = res * 10 + s.charAt(left) - '0';
left++;
}
return res >= 0 && res <= 255;
}
}
class Solution {
public List<String> restoreIpAddresses(String s) {
int len = s.length();
List<String> res = new ArrayList<>();
Deque<String> path = new ArrayDeque<>();
if(len < 4 || len > 12) return res;
dfs(s, len, 0, 4, res, path);
return res;
}
private void dfs(String s, int len, int begin, int residue, List<String> res, Deque<String> path){
if(begin == len){
if(residue == 0){
res.add(String.join(".", path));
}
return;
}
for(int i = begin; i < begin + 3; i++){
if(i >= len) break;
if(residue * 3 < len - i){
continue;
}
if(judgeIpSegment(s, begin, i)){
String str = s.substring(begin, i + 1);
path.addLast(str);
dfs(s, len, i + 1, residue - 1, res, path);
path.removeLast();
}
}
}
private boolean judgeIpSegment(String s, int left, int right){
int len = right - left + 1;
if(len > 1 && s.charAt(left) == '0'){
return false;
}
int sum = 0;
while(left <= right){
sum = sum * 10 + s.charAt(left) - '0';
left++;
}
return sum >=0 && sum <= 255;
}
}
#####################################################################################################
class Solution {
public List<String> restoreIpAddresses(String s) {
int len = s.length();
//首先定义结果集res
List<String> res = new ArrayList<>();
//因为最长就是12 最短就是4
if (len > 12 || len < 4) {
return res;
}
Deque<String> path = new ArrayDeque<>(4);
dfs(s, len, 0, 4, path, res);
return res;
}
// 需要一个变量residue 记录剩余多少段还没被分割
private void dfs(String s, int len, int begin, int residue, Deque<String> path, List<String> res) {
//当开始的位置
if (begin == len) {
if (residue == 0) {
//串联类型为 String 的 构造集合的成员,其中在每个成员之间使用指定的分隔符
res.add(String.join(".", path));
}
return;
}
//i < begin + 3的含义是:让其在三位数之间判断
for (int i = begin; i < begin + 3; i++) {
if (i >= len) {
break;
}
//len-i 是剩余字符串的长度,residue是剩余的段数,每段最长3位 即 residue * 3,若其值小于剩余长度的时候,说明不满足条件,至少应该是大于或者等于,因为每个段不一定全是3位
if (residue * 3 < len - i) {
continue;
}
if (judgeIpSegment(s, begin, i)) {
//若是一个合法的字段,则将其截取然后addLast进入path
String currentIpSegment = s.substring(begin, i + 1);
path.addLast(currentIpSegment);
//之后,因为是对同一个字符串进行操作,所以要将begin+1,然后将字段进行减一
dfs(s, len, i + 1, residue - 1, path, res);
path.removeLast();
}
}
}
private boolean judgeIpSegment(String s, int left, int right) {
int len = right - left + 1;
///当首位置是0的时候,此时前导为0,不满足要求
if (len > 1 && s.charAt(left) == '0') {
return false;
}
int res = 0;
while (left <= right) {
//不断统计 在 left和right之间的值得大小用res保存
res = res * 10 + s.charAt(left) - '0';
left++;
}
//最后返回,res是否是在0-255之内
return res >= 0 && res <= 255;
}
}