题目主要信息:有一个只包含数字的字符串,将该字符串转化成IP地址的形式需要返回所有情况,顺序没有问题举一反三:本题属于递归+回溯剪枝的类型,动态规划也可以完成,但是不如递归回溯剪枝的解释性强,因此为其他可用递归回溯方式处理的题目作参考方法一:枚举(推荐使用)思路:对于IP字符串,如果只有数字,则相当于需要我们将IP地址的三个点插入字符串中,而第一个点的位置只能在第一个字符、第二个字符、第三个字符之后,而第二个点只能在第一个点后1-3个位置之内,第三个点只能在第二个点后1-3个位置之内,且要要求第三个点后的数字数量不能超过3,因为IP地址每位最多3位数字。具体做法:step 1:依次枚举这三个点的位置。step 2:然后截取出四段数字。step 3:比较截取出来的数字,不能大于255,且除了0以外不能有前导0,然后才能组装成IP地址加入答案中。Java实现代码:import java.util.*;public class Solution {    public ArrayList<String> restoreIpAddresses (String s) {        ArrayList<String> res = new ArrayList<String>();        int n = s.length();        //遍历IP的点可能的位置(第一个点)        for(int i = 1; i < 4 && i < n - 2; i++){             //第二个点的位置            for(int j = i + 1; j < i + 4 && j < n - 1; j++){                 //第三个点的位置                for(int k = j + 1; k < j + 4 && k < n; k++){                     //最后一段剩余数字不能超过3                    if(n - k >= 4)                         continue;                     //从点的位置分段截取                    String a = s.substring(0, i);                    String b = s.substring(i, j);                    String c = s.substring(j, k);                    String d = s.substring(k);                    //IP每个数字不大于255                    if(Integer.parseInt(a) > 255 || Integer.parseInt(b) > 255 || Integer.parseInt(c) > 255 || Integer.parseInt(d) > 255)                        continue;                    //排除前导0的情况                    if((a.length() != 1 && a.charAt(0) == '0') || (b.length() != 1 && b.charAt(0) == '0') ||  (c.length() != 1 && c.charAt(0) == '0') || (d.length() != 1 && d.charAt(0) == '0'))                        continue;                    //组装IP地址                    String temp = a + "." + b + "." + c + "." + d;                     res.add(temp);                }            }        }        return res;    }}C++实现代码:class Solution {public:    vector<string> restoreIpAddresses(string s) {        vector<string> res;        int n = s.length();        //遍历IP的点可能的位置(第一个点)        for(int i = 1; i < 4 && i < n - 2; i++){             //第二个点的位置            for(int j = i + 1; j < i + 4 && j < n - 1; j++){                 //第三个点的位置                for(int k = j + 1; k < j + 4 && k < n; k++){                    //最后一段剩余数字不能超过3                    if(n - k >= 4)                         continue;                     //从点的位置分段截取                    string a = s.substr(0, i);                    string b = s.substr(i, j - i);                    string c = s.substr(j, k - j);                    string d = s.substr(k);                    //IP每个数字不大于255                    if(stoi(a) > 255 || stoi(b) > 255 || stoi(c) > 255 || stoi(d) > 255)                         continue;                    //排除前导0的情况                    if((a.length() != 1 && a[0] == '0') || (b.length() != 1 && b[0] == '0') ||  (c.length() != 1 && c[0] == '0') || (d.length() != 1 && d[0] == '0'))                        continue;                    //组装IP地址                    string temp = a + "." + b + "." + c + "." + d;                     res.push_back(temp);                }            }        }        return res;    }};Python代码实现:class Solution:    def restoreIpAddresses(self , s: str) -> List[str]:        res = []        n = len(s)        i = 1        #遍历IP的点可能的位置(第一个点)        while i < 4 and i < n - 2:             j = i + 1            #第二个点的位置            while j < i + 4 and j < n - 1:                 k = j + 1                #第三个点的位置                while k < j + 4 and k < n:                     #最后一段剩余数字不能超过3                    if n - k >= 4:                         k += 1                        continue                     #从点的位置分段截取                    a = s[0: i]                    b = s[i: j]                    c = s[j: k]                    d = s[k:]                    #IP每个数字不大于255                    if int(a) > 255 or int(b) > 255 or int(c) > 255 or int(d) > 255:                         k += 1                        continue                    #排除前导0的情况                    if (len(a) != 1 and a[0] == '0') or (len(b) != 1 and b[0] == '0') or  (len(c) != 1 and c[0] == '0') or (len(d) != 1 and d[0] == '0'):                        k += 1                        continue                    #组装IP地址                    temp = a + "." + b + "." + c + "." + d                     res.append(temp)                    k += 1                j += 1            i += 1        return res复杂度分析:时间复杂度:如果将3看成常数,则复杂度为O(1)O(1)O(1),如果将3看成字符串长度的1/4,则复杂度为O(n3)O(n^3)O(n3),三次嵌套循环空间复杂度:如果将3看成常数,则复杂度为O(1)O(1)O(1),如果将3看成字符串长度的1/4,则复杂度为O(n)O(n)O(n),4个记录截取字符串的临时变量。res属于返回必要空间。方法二:递归+回溯(扩展思路)知识点:递归递归是一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。因此递归过程,最重要的就是查看能不能讲原本的问题分解为更小的子问题,这是使用递归的关键。思路:对于IP地址每次取出一个数字和一个点后,对于剩余的部分可以看成是一个子问题,因此可以使用递归和回溯将点插入数字中。具体做法:step 1:使用step记录分割出的数字个数,index记录递归的下标,结束递归是指step已经为4,且下标到达字符串末尾。step 2:在主体递归中,每次加入一个字符当数字,最多可以加入三个数字,剩余字符串进入递归构造下一个数字。step 3:然后要检查每次的数字是否合法(不超过255且没有前导0).step 4:合法IP需要将其连接,同时递归完这一轮后需要回溯。图示:Java实现代码:import java.util.*;public class Solution {    //记录分段IP数字字符串    private String nums = "";     //step表示第几个数字,index表示字符串下标    public void dfs(String s, ArrayList<String> res, int step, int index){         //当前分割出的字符串        String cur = "";         //分割出了四个数字        if(step == 4){             //下标必须走到末尾            if(index != s.length())                 return;            res.add(nums);        }else{            //最长遍历3位            for(int i = index; i < index + 3 && i < s.length(); i++){                 cur += s.charAt(i);                //转数字比较                int num = Integer.parseInt(cur);                 String temp = nums;                //不能超过255且不能有前导0                if(num <= 255 && (cur.length() == 1 || cur.charAt(0) != '0')){                     //添加点                    if(step - 3 != 0)                         nums += cur + ".";                    else                        nums += cur;                    //递归查找下一个数字                    dfs(s, res, step + 1, i + 1);                     //回溯                    nums = temp;                 }            }        }    }    public ArrayList<String> restoreIpAddresses (String s) {        ArrayList<String> res = new ArrayList<String>();        dfs(s, res, 0, 0);        return res;    }}C++实现代码:class Solution {private:     //返回答案    vector<string> res;     //记录输入字符串    string s;     //记录分段IP数字字符串    string nums; public:    //step表示第几个数字,index表示字符串下标    void dfs(int step, int index){         //当前分割出的字符串        string cur = "";         //分割出了四个数字        if(step == 4){             //下标必须走到末尾            if(index != s.length())                 return;            res.push_back(nums);        }else{            //最长遍历3位            for(int i = index; i < index + 3 && i < s.length(); i++){                 cur += s[i];                //转数字比较                int num = stoi(cur);                 string temp = nums;                //不能超过255且不能有前导0                if(num <= 255 && (cur.length() == 1 || cur[0] != '0')){                     //添加点                    if(step - 3 != 0)                         nums += cur + ".";                    else                        nums += cur;                    //递归查找下一个数字                    dfs(step + 1, i + 1);                     //回溯                    nums = temp;                 }            }        }    }    vector<string> restoreIpAddresses(string s) {        this->s = s;        dfs(0, 0);        return res;    }};Python代码实现:class Solution:    def __init__(self):        self.res = []        self.s = ""        self.nums = ""    #step表示第几个数字,index表示字符串下标    def dfs(self, step: int, index: int):         #当前分割出的字符串        cur = ""         #分割出了四个数字        if step == 4:             #下标必须走到末尾            if index != len(self.s):                 return            self.res.append(self.nums)        else:            i = index            #最长遍历3位            while i < index + 3 and i < len(self.s):                 cur += self.s[i]                #转数字比较                num = int(cur)                 temp = self.nums                #不能超过255且不能有前导0                if num <= 255 and (len(cur) == 1 or cur[0] != '0'):                     #添加点                    if step - 3 != 0:                         self.nums += cur + "."                    else:                        self.nums += cur                    #递归查找下一个数字                    self.dfs(step + 1, i + 1)                     #回溯                    self.nums = temp                 i += 1    def restoreIpAddresses(self , s: str) -> List[str]:        self.s = s        self.dfs(0, 0)        return self.res复杂度分析:时间复杂度:O(3n)O(3^n)O(3n),3个分枝的树型递归空间复杂度:O(n)O(n)O(n),递归栈深度为nnn
点赞 31
评论 8
全部评论

相关推荐

小时候觉得老师是很伟大的职业 感觉老师都是人中龙凤才能当 后来考入大学 发现以前的老同学也是公费师范生了 他们什么样什么人品 我还不清楚吗 只能希望他们以后也会有改变 要不纯属耽误孩子 实习之后发现 有的领导 能当上领导也可能运气成分很多 自己决策方面很差 分配给属下的东西自己也说不明白  前些年那些明星 各种塌房 少林寺大师都能有情人和孩子 越长大越发现世界就是个草台班子 以前对不懂的东西有一层羡慕的滤镜 接触之后发现就不是那回事了
RazerYang:其实也是幸存者偏差,你只关注草台班子的部分,所以觉得世界都是草台班子。实际上你每天能安全地从床上醒来,有稳定的天然气、自来水和电力供应,能让你吃上热乎的饭菜,能收到持续稳定的信号去刷手机,花几块钱就能坐地铁从城市的一端快速移动到另一端,花几百块就能在一天之内安全穿越整个国家,这都不是一个草台班子能实现的。燃气、水利、电力、通信、公交、民航,还有最重要的公安和国防,这些都不是草台班子能做的,有无数普通人构筑了你生活的方方面面,而你也将加入他们。
我对___祛魅了
点赞 评论 收藏
分享
07-23 15:05
门头沟学院 Java
熊大不大:不好意思KPI数据刚刚刷新,刚刚达标
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
昨天 11:32
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务