您的位置:首页 > 其它

DFS-lintcode恢复ip地址(Restore IP Addresses)

2017-10-11 15:27 1031 查看


典型的DFS找满足条件的所有可行解。ip地址由4部分组成,每部分范围为0-255,容易忽略的是:每部分中0是可行的,但多个连续0如192.168.000.1是非法的,192.168.001.1这样前面有多余0的也是非法的,关键在于如何将这些条件转化为深搜中的条件

不熟悉深搜的可以先看看求排列组合的深搜题:DFS求全排列        DFS求组合

分析样例,第一部分的所有可能为2,25,255,若第一部分为2,则问题转化为将后续的5525511135分为3部分....以此类推,借助一个图来分析:



图中只画了一部分,首先我们将2看成第一部分,那么第二部分就有5,52,525这3中情况,525超过了255,不符合;若第二部分为5,则继续往下推又有3种........到这里我们已经可以归纳出搜索的思路:

start初值为0,我们每次处理的字符串为[start,n-1],循环i,i的范围为[start,start+2],遍历出3种可能,判断是否合法,start到达n即结束

还需要设置一个step,初值为0,表示当前正处理的ip地址的第step部分,step值为4的时候表示0,1,2,3部分已找出,结束

处理第step部分时(第step还未确定),还剩下4-step没确定,故剩下的字符串长度的范围为[4-step,(4-step)*3]

分析到这里代码已经基本成型

class Solution {
public:
/*
* @param s: the IP string
* @return: All possible valid IP addresses
*/
vector<string> restoreIpAddresses(string &s) {
// write your code here
vector<string> res;
string tmp;
DFS(s,res,tmp,0,0);
return res;
}
void DFS(string& s,vector<string>& res,string tmp,int start,int step){
//收敛条件
if(start==s.size() && step==4){
tmp.resize(tmp.size()-1);//去除最后一个.
res.push_back(tmp);
return;
}
//根据长度进行剪枝
if(s.size()-start>(4-step)*3) return;
if(s.size()-start<(4-step)) return;
int num=0;
//状态的扩展
for(int i=start;i<start+3;++i){
num=num*10+(s[i]-'0');
if(num<=255){//合法
tmp+=s[i];
DFS(s,res,tmp+'.',i+1,step+1);
}
if(num==0) break;
}
}
};还剩一个问题,这样写为什么允许了单个0而排除了连续0?
只用了if(num==0) break;这一条语句,要执行这条语句,必须要从上面的DFS递归中返回

若当前为单个0,则满足<=255,进入递归,递归返回后,表示这部分为单个0的所有可能已经处理完了

若向后循环,则可能出现这一部分为连续0,0后跟数字(000,001)这些都不能作为IP地址4部分的1部分,故直接break就好
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dfs leetcode lintcode