复原IP地址

题目描述
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
有效的 IP 地址正好由四个整数(每个整数位于 0 到 255 之间组成),整数之间用 '.' 分隔。
示例

输入: "25525511135"
输出: ["255.255.11.135", "255.255.111.35"]

递归方法
需要找出所有可能复原的IP地址,因此可以考虑使用递归的方法,对所有可能的字符串分割方法进行搜索,并筛选出满足要求的作为答案
假设题目中给出的字符串为s,使用递归函数dfs(segId,segStart)表示从s[segStart]的位置开始,搜索IP地址中的第segId段,其中segId∈{0,1,2,3,}。由于IP字段都为0-255的整数,因此从segStart开始,从小到大依次枚举当前这一段IP地址的阶数位置segEnd。如果满足要求,就递归的进行下一段搜索,调用递归函数dfs[segId+1,segEnd+1].
特殊情况

由于IP地址的每一段不能有前导0,如果s[segStart]等于字符0,那么IP地址的第segId段只能为0

在递归搜索的过程中,如果已经得到了全部的4段ip地址(即segId= 4),并且遍历完了整个字符串(即segStart= |s|,其中|s|表示字符串s的长度),那么此时就是要求的答案之一,将其加入答案。在其他时刻,如果提前遍历完了字符串,需要结束遍历,回溯到上一步。

class Solution {
private:
    static constexpr int SEG_COUNT = 4;
private:
    vector<string> ans;
    vector<int> segments;
public:
    void dfs(const string &s,int segId,int segStart)
    {
        //如果找到了4段ip,并遍历完了字符串,那就是一种答案
        if(segId == SEG_COUNT)
        {
            if(segStart == s.size())
            {
                string ipAddr;
                for(int i = 0;i < SEG_COUNT;i++)
                {
                    ipAddr += to_string(segments[i]);
                    if(i != SEG_COUNT-1)
                    {
                        ipAddr +=".";
                    }
                }
                ans.push_back(move(ipAddr));
            }
            return ;
        }
        //如果还没有找到4段ip地址就遍历完了字符串,那么提前回撤
        if(segStart == s.size())
        {
            return;
        }
        //由于不能有前导0,如果当前数字为0,那么这段IP地址只能为0
        if(s[segStart] =='0')
        {
            segments[segId] = 0;
            dfs(s,segId+1,segStart+1);
        }
        //一般情况
        int addr = 0;
        for(int segEnd = segStart;segEnd < s.size();segEnd++)
        {
            addr = addr * 10 + (s[segEnd]-'0');
            if(addr > 0 && addr <= 0xFF)
            {
                segments[segId] = addr;
                dfs(s,segId+1,segEnd+1);
            }
            else
            {
                break;
            }
        }
    }

    vector<string> restoreIpAddresses(string s) {
        segments.resize(SEG_COUNT);
        dfs(s,0,0);
        return ans;
    }
};

知识小讲堂:
C++ 11 std::move()

是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝,它就是为性能而生

c++ to_string()

功能就是将数值转换成字符串,返回对应的字符串

vector容器的resize()方法

作用是改变vector容器中元素的数目

vector容器的reserve()方法

作用是设置容器的容量

posted @ 2020-08-09 09:47  牛犁heart  阅读(510)  评论(0编辑  收藏  举报