93.复原IP地址

93.复原IP地址

题目

给定一个只包含数字的字符串,用以表示一个 IP 地址,返回所有可能从 s 获得的 有效 IP 地址 。你可以按任何顺序返回答案。

有效 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 地址。

示例 1:

输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]
示例 2:

输入:s = "0000"
输出:["0.0.0.0"]
示例 3:

输入:s = "1111"
输出:["1.1.1.1"]
示例 4:

输入:s = "010010"
输出:["0.10.0.10","0.100.1.0"]
示例 5:

输入:s = "101023"
输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/restore-ip-addresses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

思路

这道题感觉和131题分割字符串有点像
区别:这道题明确了切三次
相同点:思路是先考虑可以分割成哪些字串,再考虑字串是否符合规定

切割问题就可以使用回溯搜索法把所有可能性搜出来

image

递归的参数和返回值
每一条路径都是一个字符串,那么应该从分隔符.来确定分割的次数,就需要一个参数pointNum来记录分隔符的数量,分隔符的数量为3说明切了三次,说明递归结束了。
startIndex来记录起始的位置

List<String> res;
StringBuffer path;//需要频繁操作字符串
void backtracking(String s,int pointNum,int startIndex);

递归的终止条件

pointNum==3说明了分割了三次,分割三次后,如果剩下的字符串符合条件则把该path加入res集合

if(pointNum==3){
	//StringBuffer转换成string,判断合法函数区间[start,end];
    	 if(isValue(s,startIndex,s.length()-1))
		 {
		 path.add(s.substring(startIndex))
		 res.add(path.toString());
		 }
	return;
}

判断字符串合法函数
因为截取字符串是消耗性能的,因此,采用传子串下标的方式判断一个子串是否是符合规则,不符合规则就不需要截取了

参数
String s
判断区域[start,end]
返回值
true 符合规则
false 不符合规则
规则
1.0~255之间
2.不能0开头
3.除数字以外的值

 boolean isValue(String s,int start,int end){
      //0开头的数字
      if(s.charAt(start)=='0'&& start!=end)  return false;
	  int num = 0;
      for(int i=start;i<=end;i++){
	   //除数字以外的
		if(s.charAt(i)>'9'||s.charAt(i)<'0')return false;
		//计算方式 字符串中的数字依次取出+本次的数值
		num = num*10+s.charAt(i)-'0';
		if(num>255)return false;
       }
	   return true;
    }

单层递归逻辑

剪枝:如果有一个字串的长度超过4了,那么必然不可能,不用进入判断合法函数判断,后面长度5、长度6..也不用继续循环了

注意回溯的适合需要把原来添加的子串和 . 一起删除。
错误
这里我删.的时候用了path.deleteCharAt(path.lenthg()-1)这个是错误的,没有考虑255.255.11.135这种情况!
正确的做法path.deleteCharAt(path.lastIndexOf(".");删除添加的最后一次出现的.(也就是最后添加的.)删除之后是255.255.11135,再删除11135,最后对11135重新进行截取

for(int i = startIndex; i<s.length();i++){
	//剪枝
	if(i-startIndex==3)break;
	//先判断当前子串是否合法,不合法就采用下一种截法
	if(!isValue(s,startIndex,i))continue;
	//说明合法了
	 path.append(s.substring(startIndex,i+1));
	 path.append('.');
	 backtracking(s,pointNum+1,i+1);
	 //这里回溯还要把原来添加的s.substring(startIndex,i+1)和'.'一起删除了
	 path.deleteCharAt(path.lastIndexOf(".");
         int pointLastNum = path.lastIndexOf(".");
         path.delete(pointLastNum + 1, path.length());
}

代码

class Solution {
    List<String> res;
    StringBuffer path;
    public List<String> restoreIpAddresses(String s) {
        res = new ArrayList<>();
        path = new StringBuffer();
        if(s.length()>12)return res;
        backtracking(s,0,0);
        return res;
    }
  void  backtracking(String s,int pointNum,int startIndex){
        if(pointNum==3){
	        if(isValue(s,startIndex,s.length()-1)){
                 path.append(s.substring(startIndex));
                 res.add(path.toString());
            }
        	return;
        }
        for(int i = startIndex; i<s.length();i++){
	        if(isValue(s,startIndex,i)){
                path.append(s.substring(startIndex,i+1));
	            path.append('.');
	            backtracking(s,pointNum+1,i+1);
	            path.deleteCharAt(path.lastIndexOf("."));
                int pointLastNum = path.lastIndexOf(".");
                path.delete(pointLastNum + 1, path.length());

            }else{
                break;
            };
         }
    }
 boolean isValue(String s,int start,int end){
      if(start>end) return false;
      if(s.charAt(start)=='0'&& start!=end)  return false;
	  int num = 0;
      for(int i=start;i<=end;i++){
		if(s.charAt(i)>'9'||s.charAt(i)<'0')return false;
		num = num*10+(s.charAt(i)-'0');
		if(num>255)return false;
       }
	   return true;
    }
}

总结

String 纯数字类型与int类型的转换

String纯字符串转int

Integer.parseInt(str);

其他类型转String

//方法1
String.valueOf( value); // 其中 value 为任意一种数字类型。
//方法2
Integer.toString(i);
//方法3 常用
 "" + i;

复习一下之前学习的char数字类型转换与int类型的转换

//int型转化成char数字型型
(char) (1+'0')  //49,这里会把'0'转化成ASC码+1 = '1'

//char数字型转化成int类型
('1'-'0')  //ASC码相减=int
posted @ 2021-06-09 22:16  rananie  阅读(144)  评论(0编辑  收藏  举报