39. 组合总和
简单,略
40.组合总和II
要点是如何避免重复的组合出现?类似的思路其实在练习双指针的时候已经使用过。将递归的过程看作一棵树的生长过程的话,避免重复就是避免相同的数字在树的某一层中重复出现。(这里说的一层当然是由同一个父节点延申出来的)。为此只要先将存放可用数字的数组candidates进行排序,然后检查当前准备添加到track中的数字是否与candidates中在它前一位的数字相同,若相同则直接进入下一轮循环。
131.分割回文串
首先要明确怎么找出回文串?(小tip:单独一个字母也是回文串)我的思路是,回文串的两头一定是相等的,所以只需要固定开头,移动尾部,如果发现守卫相等,则首尾同步收缩,直至确认找到了回文串/当前首尾无法构成回文串。 确定了找回文串的策略之后,找回文串的函数签名也就可以确定:参数是给定的字符串以及搜索区间的左右边界,返回值是bool表明当前边界是否可以构成回文串;
搞定了回文串的搜索,再来考虑整体的递归。我采用的是从最大回文串开始搜索的方法。首先把搜索范围定为字符串的开头和结尾,搜索失败则收缩右边界直到搜索到以字符串0下标开头的最长子串,将该子串加入track。随后将搜索范围改为[right+1,end],如此反复直到搜索范围变成[end+1,end],即找到了第一种分割法。至此函数便会一路返回到第一层,继续搜索更短的以string[0]为首的回文串,最后一种被考虑的情况则是回文串仅由一个字母构成
class Solution {
public:
vector<string> track;
vector<vector<string>> result;
vector<vector<string>> partition(string s) {
backTrack(0,s);
return result;
}
void backTrack(int index,string &s){
if(index==s.size()){
result.push_back(track);
return;
}
for(int right=s.size()-1;right>=index;right--){
if(isPalindrome(s,index,right)){
track.push_back(s.substr(index,right-index+1));
backTrack(right+1,s);
track.pop_back();
}
}
return;
}
bool isPalindrome(string &s,int left,int right){
if(left>right) return false;
while(left<=right){
if(s[left]!=s[right]){
return false;
}else{
if(left+1==right || left==right){
return true;
}else{
left++;
right--;
}
}
}
return false;
}
};