现在有一个只包含数字的字符串,将该字符串转化成IP地址的形式,返回所有可能的情况。
例如:
给出的字符串为"25525522135",
返回["255.255.22.135", "255.255.221.35"]. (顺序没有关系)
数据范围:字符串长度
要求:空间复杂度
,时间复杂度
注意:ip地址是由四段数字组成的数字序列,格式如 "x.x.x.x",其中 x 的范围应当是 [0,255]。
"25525522135"
["255.255.22.135","255.255.221.35"]
"1111"
["1.1.1.1"]
"000256"
[]
import java.util.*;
public class Solution {
public ArrayList<String> restoreIpAddresses(String s) {
ArrayList<String> res = new ArrayList<>();
if (s.length() < 4 || s.length() > 12) {
return res;
}
dfs(res, s, new ArrayList<>(), 0);
return res;
}
void dfs(ArrayList<String> res, String s, ArrayList<String> tmp, int start) {
// 终止条件:找到4段且用完所有字符
if (tmp.size() == 4) {
if (start == s.length()) {
res.add(String.join(".", tmp));
}
return;
}
// 尝试当前段的1-3个字符
for (int len = 1; len <= 3; len++) {
if (start + len > s.length()) {
break; // 超出字符串长度
}
String segment = s.substring(start, start + len);
// 检查段的有效性
if (isValid(segment)) {
tmp.add(segment);
dfs(res, s, tmp, start + len);
tmp.remove(tmp.size() - 1); // 回溯
}
}
}
boolean isValid(String segment) {
// 检查前导0
if (segment.length() > 1 && segment.charAt(0) == '0') {
return false;
}
// 检查数值范围
int num = Integer.parseInt(segment);
return num >= 0 && num <= 255;
}
} import java.util.*;
public class Solution {
private ArrayList<String> res = new ArrayList<>(); // 结果集合
private StringBuilder path = new StringBuilder(); //一次结果
public ArrayList<String> restoreIpAddresses (String s) {
// write code here
bracktrack(s, 0, 0);
return res;
}
// 回溯
private void bracktrack(String s, int k, int from) {
if (k == 4) { // 出口
if (checkIP(path.toString())) res.add(path.toString());
return;
}
// 可以选择1位2位or3位
for (int d = 1; d <= 3; d++) {
int rest = s.length() - from - d;
if (rest > (3 - k) * 3 || rest < 3 - k) // 剩余长度太长or短
continue;
path.append(s.substring(from, from + d)); // 选择
if (k < 3) path.append(".");
bracktrack(s, k + 1, from + d); // 下一层
path.delete(path.lastIndexOf(s.substring(from, from + d)),path.length()); //撤销
}
}
// 检查IP地址
private boolean checkIP(String IP) {
String[] ip = IP.split("\\.");
if (ip.length != 4) return false; // 4段
for (String s : ip) {
if (s.isEmpty()) return false; // 非空
if (s.startsWith("0") && !s.equals("0")) return false; // 不含前导0
if (Integer.parseInt(s) > 255) return false; // 0-255
}
return true;
}
} import java.util.*;
public class Solution {
public ArrayList<String> restoreIpAddresses (String s) {
// write code here
ArrayList<String> ans = new ArrayList<>();
List<String> choice = new ArrayList<>();
dfs(0, s, ans, choice);
return ans;
}
private void dfs(int start, String s, ArrayList<String> ans, List<String> choice) {
if (start == s.length()) {
if (choice.size() == 4) {
StringBuilder sb = new StringBuilder();
for (String c : choice) {
sb.append(c);
sb.append(".");
}
sb.deleteCharAt(sb.length()-1);
ans.add(sb.toString());
}
return;
}
for (int i = start; i < start+3 && i < s.length(); i++) {
String temp = s.substring(start, i+1);
int num = Integer.parseInt(temp);
// 该段host号要在[0, 255]之内,且要避免"00"或者"000"的划分出现
if (num >= 0 && num <= 255 && (temp.length() == 1 || temp.charAt(0) != '0')) {
choice.add(temp);
dfs(i+1, s, ans, choice);
choice.remove(choice.size()-1);
}
}
}
}
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return string字符串ArrayList
*/
public ArrayList<String> restoreIpAddresses (String s) {
// write code here
// 算法:分支限界的递归回溯
// 处理特殊情况:
ArrayList<String> result = new ArrayList<>();
if (s.length() < 4) {
return result;
}
ArrayList<Integer> nums = new ArrayList<>();
result = process(s, 0, nums);
return result;
}
public ArrayList<String> process (String s, int i, ArrayList<Integer> nums) {
int len = s.length();
ArrayList<String> result = new ArrayList<>();
// 递归出口
if (nums.size() == 4 && i == len) {
StringJoiner sj = new StringJoiner(".");
for (Integer num : nums) {
if (num >= 0 && num <= 255) {
sj.add(num.toString());
} else {
// 划分错误
return null;
}
}
result.add(sj.toString());
return result;
} else if (nums.size() == 4 && i < len) {
// 划分错误
return null;
} else if (nums.size() < 4 && i == len) {
// 划分错误
return null;
}
// 递归分支 - 最多三种情况
// 这里写的不太好,判断的逻辑全是“补丁”,但答案确实是对的
for (int j = 1; j <= 3; j++) {
if (i + j > len) {
// 下标越界了,不必再往后划分了
break;
}
String sub = s.substring(i, i + j);
if (sub.length() > 1 && sub.startsWith("0")) {
// 以0开头的多位数不合法,不必再往后划分了
break;
}
int subNum = Integer.parseInt(sub);
if (subNum > 255) {
// 当前数超过255不合法,不必再往后划分了
break;
}
nums.add(subNum);
ArrayList<String> add = process(s, i + j, nums);
if (add != null) {
result.addAll(add);
}
// 注意恢复现场
nums.remove(nums.size() - 1);
}
return result;
}
} List<List<String>> resList = new ArrayList<>();
public ArrayList<String> restoreIpAddresses (String s) {
// write code here
backTrace(s, 0, new LinkedList<>());
// 转格式
return (ArrayList<String>)resList.stream().map(row -> String.join(".", row))
.collect(Collectors.toList());
}
public void backTrace(String str, int i, LinkedList<String> tempList) {
// ip固定为4组数字, 大于4的情况需要舍弃
if (tempList.size() > 4) {
return;
}
// 长度为4, 并且i已经走到字符串末尾, 则保存结果, 否则舍弃
if (tempList.size() == 4) {
if (i == str.length()) {
resList.add(new ArrayList<>(tempList)); // 注意这里需要new ArrayList来深拷贝, 不然结果为空
}
return;
}
// 数字长度只能有三种情况, 即长度为1, 长度为2, 长度为3
for (int k = 1; k <= 3; k++) {
if (i + k > str.length()) break;
String tempStr = str.substring(i, i + k);
int tempNum = Integer.parseInt(tempStr);
// 排除以0开头的, 并且长度大于1的情况, 如00, 001, 09 ...等等
// 如果有0开头,那么必须是0本身才符合条件
if (tempStr.startsWith("0") && tempStr.length() > 1) break;
if (tempNum >= 0 && tempNum <= 255) {
tempList.addLast(tempStr);
backTrace(str, i + k, tempList);
tempList.removeLast();
}
}
} public class Solution {
public void recursion(List<String> result, String s, StringBuilder temp, int segmentCount, int index) {
if (segmentCount == 4 && index == s.length()) {
result.add(temp.toString());
return;
}
if (segmentCount >= 4 || index >= s.length()) {
return;
}
int currTempLength = temp.length();
for (int i = 1; i <= 3 && index + i <= s.length(); i++) {
String segment = s.substring(index, index + i);
if (isValidSegment(segment)) {
temp.append(segment);
if (segmentCount < 3) {
temp.append(".");
}
recursion(result, s, temp, segmentCount + 1, index + i);
temp.setLength(currTempLength);
}
}
}
public boolean isValidSegment(String segment) {
if (segment.length() >= 2 && segment.charAt(0) == '0') {
return false;
}
int num = Integer.parseInt(segment);
return num >= 0 && num <= 255;
}
public ArrayList<String> restoreIpAddresses(String s) {
ArrayList<String> result = new ArrayList<>();
if (s == null || s.length() < 4 || s.length() > 12) {
return result;
}
recursion(result, s, new StringBuilder(), 0, 0);
return result;
}
} import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return string字符串ArrayList
*/
public ArrayList<String> restoreIpAddresses (String s) {
// write code here
//先过滤掉不符合条件的
if (s.length() < 4 || s.length() > 12) {
return new ArrayList<>();
}
StringBuilder sb = new StringBuilder();
ArrayList<String> res = new ArrayList<>();
dfs(s, sb, res, 0, 0);
return res;
}
public void dfs(String s, StringBuilder sb, ArrayList<String> res, int pointSum,
int start) {
//如果逗号数量为3,则说明分割完成了
if (pointSum == 3) {
//再对最后一层循环的字符进行判断是否合法
//左闭塞右开
String sTemp = s.substring(start, s.length());
if (isValid(sTemp)) {
sb.append(sTemp);
res.add(new String(sb.toString()));
sb.delete(sb.length() - sTemp.length(), sb.length());
// sb.setLength(sb.length() - sTemp.length());
return;
}
}
// 检查索引是否超出范围
if (start >= s.length()) {
return;
}
for (int i = start; i < s.length(); i++) {
//截取的字符
String sTemp = s.substring(start, i + 1);
//判断是否合法
if (!isValid(sTemp)) {
//不合法就结束递归
return;
} else {
// int lengthBeforeAppend = sb.length();
sb.append(sTemp).append(".");
pointSum++;
dfs(s, sb, res, pointSum, i + 1);
//记得删除逗号
// sb.setLength(lengthBeforeAppend);
sb.delete(sb.length() - sTemp.length() - 1, sb.length());
pointSum--;
}
}
}
// 校验函数
public boolean isValid(String s) {
if (s.length() == 0 || (s.charAt(0) == '0' && s.length() != 1)) {
return false;
}
int a = Integer.parseInt(s);
return a >= 0 && a <= 255;
}
}
简单易懂
ArrayList<String> res=new ArrayList<>();
int len=s.length();
// 左闭右开,校验偏移量
for(int i=1;i<4;i++){
for(int j=i+1;j<i+4;j++){
for(int k=j+1;k<j+4;k++){
if(k>=len || k+3<len){
continue;
}
String s1=s.substring(0 ,i);
String s2=s.substring(i ,j);
String s3=s.substring(j ,k);
String s4=s.substring(k ,len);
if(isOK(s1) && isOK(s2) && isOK(s3) && isOK(s4)){
res.add(s1+"."+s2+"."+s3+"."+s4);
}
}
}
}
return res;
}
public boolean isOK(String str){
if(str.charAt(0)=='0' && str.length()>1){
return false;
}
int num=Integer.parseInt(str);
return num>=0 && num<=255;
} import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return string字符串ArrayList
*/
private String s;
private ArrayList<String> ans=new ArrayList<>();
public ArrayList<String> restoreIpAddresses (String s) {
this.s=s;
dfs(new ArrayList<>(),0);
return ans;
}
public void dfs(List<String> path,int idx){
if(path.size()>=4){
if(path.size()==4&&idx==s.length()){
ans.add(convert(path));
}
return;
}
for(int i=idx+1;i<=s.length();i++){
String si=s.substring(idx,i);
int x=Integer.parseInt(si);
if(s.charAt(idx)=='0'&&si.length()>1) break;
if(x<=255&&x>=0){
path.add(si);
dfs(path,i);
path.remove(path.size()-1);
}else{break;}
}
}
public String convert(List<String> path){
StringBuilder sb=new StringBuilder();
for(int i=0;i<path.size();i++){
if(i!=0) sb.append('.');
sb.append(path.get(i));
}
return sb.toString();
}
} public class Solution {
/**
*
* @param s string字符串
* @return string字符串ArrayList
*/
public ArrayList<String> restoreIpAddresses (String s) {
// write code here
List<Integer> list = new ArrayList<>();
dfs(s, 0, list);
return res;
}
ArrayList<String> res = new ArrayList<>();
String getFromArray(List<Integer> list) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.size(); i++) {
sb.append(list.get(i));
if (i != list.size() - 1) {
sb.append(".");
}
}
return sb.toString();
}
void dfs(String s, int idx, List<Integer> list) {
if (idx >= s.length()) {
if (list.size() == 4) {
res.add(getFromArray(list));
}
return;
}
if (list.size() >= 4) {
return;
}
if (s.charAt(idx) == '0') {
list.add(0);
dfs(s, idx + 1, list);
list.remove(list.size() - 1);
return;
}
for (int i = idx; i < idx + 3 && i < s.length(); i++) {
int temp = Integer.valueOf(s.substring(idx, i + 1));
if (temp >= 0 && temp <= 255) {
list.add(temp);
dfs(s, i + 1, list);
list.remove(list.size() - 1);
}
}
}
} import java.util.*;
public class Solution {
/**
*
* @param s string字符串
* @return string字符串ArrayList
*/
public ArrayList<String> restoreIpAddresses (String s) {
// write code here
ArrayList<String> ans=new ArrayList<>();
build(s,0,0,ans);//startIndex,end
return ans;
}
public void build(String s,int startIndex,int pointNum,ArrayList<String> ans){
if(pointNum==3){
if(isVaild(s,startIndex,s.length()-1)){
ans.add(s);
}
return;
}
for(int i=startIndex;i<s.length();i++){
if(isVaild(s,startIndex,i)){
pointNum++;
s=s.substring(0,i+1)+"."+s.substring(i+1);
build(s,i+2,pointNum,ans);
pointNum--;
s=s.substring(0,i+1)+s.substring(i+2);
}
}
}
public boolean isVaild(String s,int startIndex,int end){
if(startIndex>end){
return false;
}
if(s.charAt(startIndex)=='0'&&startIndex!=end){
return false;
}
int num=0;
for(int i=startIndex;i<end+1;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;
}
} import java.util.*;
public class Solution {
/**
*
* @param s string字符串
* @return string字符串ArrayList
*/
public ArrayList<String> restoreIpAddresses (String s) {
if (s.length() < 4) {//长度小于4的不可能组成ip
return new ArrayList<String>();
}
//dp[i]表示i下标及之前的字符串可能的所有ip地址集合
ArrayList dp[] = new ArrayList[s.length()];
for (int i = 0; i < s.length(); i++) {
ArrayList<String> newList = new ArrayList<>();
//满足当前数字单独为一个数字
append(dp,""+s.charAt(i),newList,i-1,i==s.length()-1);
//满足当前数字连接前面一个
if (i >= 1 && (s.charAt(i - 1) * 10 + s.charAt(i) - 11 * '0' >= 10)) {
String cur = "" + s.charAt(i - 1) + s.charAt(i);
append(dp,cur,newList,i-2,i==s.length()-1);
}
//满足当前数字连接前面两个
if (i >= 2 &&
(s.charAt(i - 2) * 100 + s.charAt(i - 1) * 10 + s.charAt(i) - 111 * '0' <= 255) &&
(s.charAt(i - 2) * 100 + s.charAt(i - 1) * 10 + s.charAt(i) - 111 * '0' >= 100)) {
String cur = "" + s.charAt(i - 2) + s.charAt(i - 1) + s.charAt(i);
append(dp,cur,newList,i-3,i==s.length()-1);
}
dp[i] = newList;
}
return dp[s.length() - 1];
}
public void append(ArrayList[] dp, String cur,ArrayList<String> newList, int index, boolean isEnd) {
if(index==-1){
newList.add(cur);
}else{
ArrayList<String> left = dp[index];
for(String str:left){
int len = str.split("\\.").length;
if(len<=3&&(!isEnd||len==3)){
newList.add(str + "." + cur);
}
}
}
}
} import java.util.*;
public class Solution {
/**
*
* @param s string字符串
* @return string字符串ArrayList
*/
public ArrayList<String> restoreIpAddresses (String s) {
// write code here
ArrayList<String> res = new ArrayList<>();
ArrayList<String> temp = new ArrayList<>();
dfs(s, 0, res, temp);
return res;
}
private void dfs(String s, int index, ArrayList<String> res,
ArrayList<String> temp) {
if (temp.size() == 4) { //满足ip组数可能是结果
if (index == s.length()) { //确实对s全部遍历过
res.add(String.join(".", temp));
}
return;//没遍历过,不是解
}
for (int i = index; i < s.length() && i < index + 3; i++) {
String sub = s.substring(index, i + 1); //截取字符串
if (isCheck(sub)) {//符合ip规则
temp.add(sub);
dfs(s, i + 1, res, temp);
temp.remove(temp.size() - 1);//回溯
}
}
}
private boolean isCheck(String sub) {
if (sub.length() != 1 && sub.charAt(0) == '0') return false;//前缀零
int num = Integer.parseInt(sub);
return num >= 0 && num <= 255;
}
} public class Solution {
/**
*
* @param s string字符串
* @return string字符串ArrayList
*/
public ArrayList<String> restoreIpAddresses (String s) {
ArrayList<String> result = new ArrayList<>();
restoreIpAddresses (s, result, "", 0);
return result;
}
/**
*
* @param s 待处理的字符串
* @param result // 最终保存正确ip地址的集合
* @param concat // 拼接的合法ip地址
* @param pointSum // 标识当前处理的是第几段ip
*/
public void restoreIpAddresses (String s, ArrayList<String> result, String concat,int pointSum) {
if(s.length() == 0) return;
// 表示当前查找第几段ip
pointSum++;
// 说明前三段已经找到了,该第四段,但是最后一段在这里判断就可以
if(pointSum == 4){
// 此处无需判断s字符串长度是否大于3,因为能递归到这里,s这个字符串的长度一定合法 (下面循环中做了处理)
// 如果最后一段字符串s 转int大于255 或者 s字符串长度只要大于1,并且 首位字符是0,则不合法
if(Integer.parseInt(s) > 255 || (s.length() > 1 && s.charAt(0) == '0')){
return; // 结束,无需添加结果集
}
// 最后一段合法时,则拼接最后一段的字符串,添加结果集。
// 这里substr 因为首次拼接时,小数点在首位,这里切割掉
result.add(concat.substring(1) + "." + s);
return;
}
// 已知每一段最多3位,所以只循环3次
for (int i = 1; i < 4 && i <= s.length(); i++) {
// 以i切割,left左字符串,right右字符串
String left = s.substring(0, i); // left是切割的当前pointSum段的字符
String right = s.substring(i); // right是剩余未切割字符
// pointSum 标识当前已经查找到了第几段
// ip共四段,每一段最大3位。
// 当pointSum为1的时候,后面的ip还剩3段,长度不能大于 3 * 3 = 9长度
// 当pointSum为2的时候,后面的ip还剩2段,长度不能大于 3 * 2 = 6长度
// 当pointSum为3的时候,后面的ip还剩1段,长度不能大于 3 * 1 = 3长度
// 如果大于,则本次的切割可以认为无效, 下次循环继续向后切割
if( (pointSum == 1 && right.length() > 9) || (pointSum == 2 && right.length() > 6) || (pointSum == 3 && right.length() > 3) ){
continue;
}
// 如果切割后的左字符串 转int大于255 或者 左字符串长度只要大于1,并且 首位字符是0,则不合法
if(Integer.parseInt(left) > 255 || (left.length() > 1 && left.charAt(0) == '0')){
// 只要满足非法条件,可以直接return,因为下次循环只会分割的更大 或者 首位依旧还会是0
return;
}
// 以上校验完毕后,说明当前pointNum段的字符串left合法
// 那么将剩余字符right传入,并且将concat字符串参数,用.拼接left
restoreIpAddresses (right, result, concat + "." + left,pointSum);
}
}
} import java.util.*;
public class Solution {
/**
*
* @param s string字符串
* @return string字符串ArrayList
*/
ArrayList<String> res = new ArrayList<>();
String s;
public ArrayList<String> restoreIpAddresses (String s) {
// write code here
this.s = s;
StringBuilder statu = new StringBuilder();
getIpNode(statu, 0, -1);
return res;
}
void getIpNode(StringBuilder sb, int index, int count) {
if (index == s.length() && count == 3) {
res.add(sb.toString());
return;
}
if (count == 3) {
return;
}
if (index == s.length()) {
return;
}
if (count >= 0) {
sb.append(".");
}
count++;
if (s.charAt(index) == '0') {
sb.append('0');
getIpNode(sb, index + 1, count);
sb.deleteCharAt(index + count);
if (count > 0) {
sb.deleteCharAt(index + count - 1);
}
return;
}
if (s.charAt(index) > '2') {
sb.append(s.charAt(index));
getIpNode(sb, index + 1, count);
sb.deleteCharAt(index + count);
if (index + 1 < s.length()) {
sb.append(s.charAt(index)).append(s.charAt(index + 1));
getIpNode(sb, index + 2, count);
sb.delete(index + count, index + count + 2);
}
if (count > 0) {
sb.deleteCharAt(index + count - 1);
}
return;
}
if (s.charAt(index) == '1') {
sb.append(s.charAt(index));
getIpNode(sb, index + 1, count);
sb.deleteCharAt(index + count);
if (index + 1 < s.length()) {
sb.append(s.charAt(index)).append(s.charAt(index + 1));
getIpNode(sb, index + 2, count);
sb.delete(index + count, index + count + 2);
}
if (index + 2 < s.length()) {
sb.append(s.charAt(index)).append(s.charAt(index + 1)).append(s.charAt(
index + 2));
getIpNode(sb, index + 3, count);
sb.delete(index + count, index + count + 3);
}
if (count > 0) {
sb.deleteCharAt(index + count - 1);
}
return;
}
sb.append(s.charAt(index));
getIpNode(sb, index + 1, count);
sb.deleteCharAt(index + count);
if (index + 1 < s.length()) {
sb.append(s.charAt(index)).append(s.charAt(index + 1));
getIpNode(sb, index + 2, count);
sb.delete(index + count, index + count + 2);
}
if (index + 2 < s.length() && (s.charAt(index + 1) == '0' ||
s.charAt(index + 1) < '5')) {
sb.append(s.charAt(index)).append(s.charAt(index + 1)).append(s.charAt(
index + 2));
getIpNode(sb, index + 3, count);
sb.delete(index + count, index + count + 3);
}
if (index + 2 < s.length() && (s.charAt(index + 1) == '5' &&
(s.charAt(index + 2) == '0' ||
s.charAt(index + 2) <= '5'))) {
sb.append(s.charAt(index)).append(s.charAt(index + 1)).append(s.charAt(
index + 2));
getIpNode(sb, index + 3, count);
sb.delete(index + count, index + count + 3);
}
if (count > 0) {
sb.deleteCharAt(index + count - 1);
}
return;
}
} public class Solution {
/**
*
* @param s string字符串
* @return string字符串ArrayList
*/
public ArrayList<String> res = new ArrayList();
public LinkedList<String> path = new LinkedList();
public ArrayList<String> restoreIpAddresses (String s) {
// write code here
if(s.length()==0) return new ArrayList();
helper(s,0);
return res;
}
public void helper(String s, int start){
if(start == s.length()){
if(path.size()==4) res.add(String.join(".", path));
else return;
}
for(int i = start; i<s.length() && i-start<=2;i++){
String sub = s.substring(start,i+1);
if(judge(sub)){
path.add(sub);
helper(s, i+1);
path.removeLast();
}
}
}
public boolean judge(String s){
if(s.charAt(0)=='0'){
if(s.equals("0")) return true;
else return false;
}
if(Integer.valueOf(s)>255) return false;
return true;
}
}