您的位置:首页 > 其它

每天一道LeetCode-----将字符串拆分成有效的ip地址

2017-12-19 22:04 417 查看

Restore IP Addresses

原题链接Restore IP Addresses



给定一个仅包含数字的字符串,将其拆分成有效的ip地址

题目的主要意思实际是在字符串中添加三个点,从而构成一个ip地址,有效的ip地址格式为

最多包含12个数字

每个数字在[0, 255]之间

数字中除了单一0,不能出现类似0开头的数字,比如192.168.1.013中013是不允许的

所以其实就是随便找到三个位置,判断拆分成的四块数字是否满足要求即可

首先,为了易于理解,在安插”.”的过程中不记录组成的ip地址,只是将”.”的位置记录下来,当”.”的个数为3时统一计算

代码如下

class Solution {
public:
vector<string> restoreIpAddresses(string s) {
vector<string> res;
//不合法
if(s.size() > 12)   return res;
//记录"."的位置
vector<int> dots;
dfs(s, res, dots, 0);
return res;
}
private:
void dfs(string& s, vector<string>& res, vector<int>& dots, int idx)
{
if(dots.size() == 3)
{
//判断四个数字是否符合要求,然后添加
//计算one时的写法是有原因的,可以将dots[-1] 看做 -1
string one = s.substr(-1 + 1, dots[0] - (-1));
string two = s.substr(dots[0] + 1, dots[1] - dots[0]);
string three = s.substr(dots[1] + 1, dots[2] - dots[1]);
string four = s.substr(dots[2] + 1);
if(isValid(one) && isValid(two) && isValid(three) && isValid(four))
res.emplace_back(one + "." + two + "." + three + "." + four);
return;
}
//因为最后一个"."后面必须有数字,所以到s.size() - 1即可
for(int i = idx; i < static_cast<int>(s.size()) - 1; ++i)
{
//表示将"."放在s[i]的后面
dots.emplace_back(i);
dfs(s, res, dots, i + 1);
dots.pop_back();
}
}

bool isValid(string numStr)
{
if(numStr.size() > 3 || (numStr.size() > 1 && numStr.find_first_not_of('0') != 0) || (numStr.size() == 3 && numStr > "255"))
return false;
else
return true;
}
};


这种方法比较慢,主要的原因是会将所有可能都找出来然后判断是否合法,也就是说当确定第一个”.”的位置时,这个位置可能是不合适的,但是仍然需要进行到最后

深度优先和回溯法的思想在于将不合法的情况扼杀在摇篮里,也就是要确定”.”的位置时判断是否满足要求,如果不满足要求,就没必要按照这个”.”的位置进行下去

所以,需要在for循环中动手脚,判断”.”的位置是否合适。方法就是判断当前这个”.”和上一个”.”之间的数字是否符合要求,这里用prevIdx变量记录上一个”.”的位置

由上面计算one,two,three,four的公式可知,两个”.”之间的数字正是[prevIdx+1, i],其中

prevIdx记录上一个”.”的位置,初始时为-1,类似公式中的dots[0]

i是当前要确定的”.”的位置,指在s[i]后面插入”.”,类似公式中的dots[1]

有了上面的基础,代码可以更改为

class Solution {
public:
vector<string> restoreIpAddresses(string s) {
vector<string> res;
//不合法
if(s.size() > 12)   return res;
//记录"."的位置
vector<int> dots;
dfs(s, res, dots, -1, 0);
return res;
}
private:
void dfs(string& s, vector<string>& res, vector<int>& dots, int prevIdx, int idx)
{
if(dots.size() == 3)
{
//判断四个数字是否符合要求,然后添加
//计算one时的写法是有原因的,可以将dots[-1] 看做 -1
string one = s.substr(-1 + 1, dots[0] - (-1));
string two = s.substr(dots[0] + 1, dots[1] - dots[0]);
string three = s.substr(dots[1] + 1, dots[2] - dots[1]);
string four = s.substr(dots[2] + 1);
//one two three在确定"."时已经判断过
if(isValid(four))
res.emplace_back(one + "." + two + "." + three + "." + four);
return;
}
//因为最后一个"."后面必须有数字,所以到s.size() - 1即可
for(int i = idx; i < static_cast<int>(s.size()) - 1; ++i)
{
//判断是否满足要求
if(!isValid(s.substr(prevIdx + 1, i - prevIdx)))
return;
//表示将"."放在s[i]的后面
dots.emplace_back(i);
dfs(s, res, dots, i, i + 1);
dots.pop_back();
}
}

bool isValid(string numStr)
{
if(numStr.size() > 3 || (numStr.size() > 1 && numStr.find_first_not_of('0') != 0) || (numStr.size() == 3 && numStr > "255"))
return false;
else
return true;
}
};


再简单一点,可以不需要dots,在遍历的过程中就将最后的ip地址构造好

class Solution {
public:
vector<string> restoreIpAddresses(string s) {
vector<string> res;
//不合法
if(s.size() > 12)   return res;
string cur("");
dfs(s, res, cur, -1, 0, 0);
return res;
}
private:
void dfs(string& s, vector<string>& res, string& cur, int prevIdx, int idx, int count)
{
if(count == 3)
{
string four = s.substr(idx);
if(isValid(four))
res.emplace_back(cur + four);
return;
}
//因为最后一个"."后面必须有数字,所以到s.size() - 1即可
string tmp = cur;
for(int i = idx; i < static_cast<int>(s.size()) - 1; ++i)
{
//判断是否满足要求
if(!isValid(s.substr(prevIdx + 1, i - prevIdx)))
break;

cur.append(1, s[i]);
cur.append(1, '.');
dfs(s, res, cur, i, i + 1, count + 1);
//回溯的过程需要回到原来的样子,但是这里只弹出了"."的目的是为了继续扩充当前数字
//不需要回到append(1, s[i])之前的样子,但是return之前需要
cur.pop_back();
}
//当返回时回到原来的样子
std::swap(cur, tmp);
}

bool isValid(string numStr)
{
if(numStr.size() > 3 || (numStr.size() > 1 && numStr.find_first_not_of('0') != 0) || (numStr.size() == 3 && numStr > "255"))
return false;
else
return true;
}
};


本题主要思路是在s中选择三个位置作为”.”,同时确定分出的四个数字是否合法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode
相关文章推荐