回溯算法2

分割问题举例,以给定的输入字符串str=“aabbacdd”为例,将str分割成一些子串,使每个子串都是回文子串,输出所有符合的子串。注意:子串的长度不定,说明你可以任意的分割。

处理这个问题,除了使用穷举的思路,在逻辑上也没有更好的思路了。因此分割问题也是回溯算法的典型。将图中的流程进行总结。需要res保存结果,path记录分割片段。对于每一层来说,需要一个startIndex变量记录分割起点,终点在startIndex右侧任意取定。这一层的子串确定后,判定子串是否符合要求。如符合,则从下一个位置处递归开始取下一个子串。

注意:回溯的过程如果能够用树图来做的话是最直观的。

2c5633b238ec462fba61ff152c5754d2.png

vector<vector<string>> res;
vector<string> path;

bool isPalindrome(string s){
int left=0,right=s.size()-1;
while(left<=right){
if(s[left]!=s[right]){return false;}
}
return true;
}

void BackTrack(string s, int startIndex){
//终止条件,使startIndex==s.size(),才能够保证最后一个字符也计算在内,左闭右开写法
if(startIndex==s.size()) {res.push_back(path); return ;}

for(int i=startIndex;i<s.size();++i){
//剪一个枝
string s1=s.substr(startIndex, i-startIndex+1);
if(!isPalindrome(s1)){continue;}

path.push_back(s1); //startIndex所指已经是下一个字符
BackTrack(s, i+1);
path.pop_back();
}
}

复原ip地址问题。给定一组字符串str="10012116",输出所有可能的ip地址。

ip地址的格式为类似“192.168.1.12”,由4段数字+3个“.”构成,每段数字属于(0,255),且不能含有前导0,即“091”。但是“0”可以。这个过程也是穷举的,因此适合用回溯来做。用树图表示这个过程。如下。

 

//
vector<string> path;
vector<string> res;

bool isValid(string s){
//s可能为"0","00","000"
if(s.size()==1){return (s>="0" && s<="9")? true : false;}
if(s.size()==2){return s[0]!="0" ? true : false;}
if(s.size()==3){

if(s[0]=="0")return false;
int num=0;
for(int i=2;i>=0;--i){num+=(s[i]-"0")*pow(10,2-i);}
return num<=255;
}
//s有更多的位数
return false;
}
void IPRecovery(string str, int startIndex){
if(path.size()==3){
//path有3个时,从startIndex剩余的都是第四个字段了
if(!isValid(str.substr(startIndex, str.size()-startIndex))){return ;}
//所有能递归到终止条件的IP段都是正确的
//处理IP
string ip;
for(int i=0;i<path.size();++i){
ip+=path[i];
ip+=".";
}
ip+=str.substr(startIndex, str.size()-startIndex);
res.push_back(path);
return;
}

for(int i=startIndex;i<str.size();++i){

string s=str.sub(startIndex, i-startIndex+1);
if(s.size()>3)break;
if(!isValid(s)){return;}

path.push_back(s);
IPRecovery(str, i+1);
path.pop_back();
}
}

子集问题举例。

排列问题举例。

N皇后问题。

最后,举一个数独的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值