题目描述
现在有一个只包含数字的字符串,将该字符串转化成IP地址的形式,返回所有可能的情况。
例如:
给出的字符串为"25525522135",
返回[“255.255.22.135”, “255.255.221.35”]. (顺序没有关系)
示例
输入"25525522135"
返回 [“255.255.22.135”,“255.255.221.35”]
思考
我们知道IP地址分为四个小段,每一小段都是在0~255这个区间内第一小段不能为0。这个就是合法IP 的规则 根据规则我们就可以来判断如何进行。
1、字符串长度最多12位 超了直接return;
2、每一个小段最多是小于等于255。
3、第一小段不能为0。
4、从1位到3位一次递归实现 找到合适的Ip 地址。
import java.util.ArrayList;
import java.util.List;
/**
*
*
* @Title: Ip.java
* @Package com.zhonglian.ctx.consumer.web.learn
* @Description: 描述 现在有一个只包含数字的字符串,将该字符串转化成IP地址的形式,返回所有可能的情况。
* @author: drj
* @date: 2020年11月8日 下午11:08:10
* @version V1.0
* @Copyright:
*/
public class Ip {
public static void main(String[] args) {
/**
* /源字符串
*/
String sourceStr = "25525522135";
/**
* 存放目标合法ip
*/
List<String> targetList = new ArrayList<String>();
/**
* 存放临时IP
*/
StringBuilder b = new StringBuilder();
getIp(sourceStr, targetList, 0, 0,b);
System.err.println(targetList);
targetList.stream().forEach(ip ->{
System.err.println("ip:"+ ip + "是否合法:" + ipCheck(ip));
});
}
/*public static void deep(int i) {
i++;
if(i == 4) {
return;
}
System.err.println("***"+i);
deep(i);
System.err.println(i);
}*/
/**
*
* @Title: ipCheck
* @Description: TODO(正则判断ip 是否合法)
* @param: @param text
* @param: @return
* @return: boolean
* @author: Drj
* @throws
*/
public static boolean ipCheck(String text) {
if (text != null && !text.isEmpty()) {
// 定义正则表达式
String regex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."+
"(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."+
"(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."+
"(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";
// 判断ip地址是否与正则表达式匹配
if (text.matches(regex)) {
// 返回判断信息
return true;
} else {
// 返回判断信息
return false;
}
}
return false;
}
/**
*
* @Title: getIp
* @Description: TODO递归获取合法IP)
* @param: @param sourceStr
* @param: @param targetList
* @param: @param startPoint 已经截取的长度
* @param: @param count 段数
* @param: @param b
* @return: void
* @author: Drj
* @throws
*/
public static void getIp(String sourceStr,List<String> targetList,int startPoint,int count,StringBuilder b) {
/**
* 判断剩余长度是否最大允许的长度
* eg:ip 地址最长除了点 应该是255.255.255.255 12的位的字符串 当超过12位 就可以判断不符合要求
* 在eg: 当你第一位是一位数1.255.255.255 剩余最大是能是9位 所以得出一个公式
* 目标字符串的长度 - 使用的长度 > 3* (4- 节数) 其实3 的意思每节最多是3位 一个合法ip 固定4节
* 超了没必要 继续递归 直接return
*/
if ((sourceStr.length() - startPoint) > (3 * (4 - count))) {
return;
}
/**
*判断剩余长度是否最小允许长度
*eg:由于四段所以至少每位有一个 最少有4位数字 所以 (总长度- 已经截取的长度 )要是小于了( 4 - 已经合成的段数)就没必要再去递归直接return
*/
if((sourceStr.length() -startPoint) < 4 - count) {
return;
}
/**
* 当段数 超过4 直接返回 因为 iP 最大只有4段
*/
if(count > 4) {
return;
}
/**
* 当段数等于4的时候 同时 截取长度 等于源字符串长度 说明 字符串都被使用同时也符合合法的段数
* 这时候将该存储组成的ip 做一个是否合法判断。因为我们第一步是一个比较粗的过滤 通过正则过滤是完善的更合法的Ip
*/
if (startPoint == sourceStr.length() && count == 4) {
/**
* b 长度减一目的是截取了最后一位的点(.)字符。
*/
String ip = b.toString().substring(0, b.length() - 1);
/**
* 判断是否合法 合法添加到目标集合
*/
if(ipCheck(ip)){
targetList.add(ip);
}
return;
}
StringBuilder t = null;
/**
* 当段位数为1的时候
*/
if(startPoint + 1 <= sourceStr.length()) {
t = new StringBuilder(b);
String temp = sourceStr.charAt(startPoint) + ".";
b.append(temp);
getIp(sourceStr,targetList,startPoint+1,count+1,b);
}
/**
* 当段位数为2的时候
*/
if(startPoint + 2 <= sourceStr.length()) {
b = new StringBuilder(t);
b.append(sourceStr.substring(startPoint, startPoint + 2) + "" + '.');
getIp(sourceStr, targetList, startPoint + 2, count + 1, b);
}
/**
* 当段位数为3的时候 同时判断 三位数字不能大于255 超了直接return
*/
if(startPoint + 3 <= sourceStr.length()) {
b = new StringBuilder(t);
String tempThree = sourceStr.substring(startPoint, startPoint + 3);
Integer v = Integer.valueOf(tempThree);
if(v > 255) {
return;
}
t.append(sourceStr.substring(startPoint, startPoint + 3) + "" + '.');
getIp(sourceStr, targetList, startPoint + 3, count + 1, t);
}
}
}