131.分割回文串

  • 131.分割回文串
  • 思路:
    要想把一个string分割为几个子string串,且必须都是回文串。由于分割位置任意,分割次数也任意(即没要求分成几块);
    因此考虑回溯法遍历,将每个位置都尝试作为分割处;若某个字串不是回文,则尝试将分割线后移,也就是说,不能出现两个回文串中间夹一个非回文串的情形,必须是连着都是回文串;那我们就必须要求,若从i位置开始找的话,分别尝试从i开始长度为1的字串,为2的字串。。。分别去判断是不是回文串,假如说[i, i+1]这一段是个回文串,那么才能尝试从i+2以起始点寻找下一个回文串;若以i为起始点往后找,一直找到string主串末尾都没找到回文串,说明按前面分割的思路分到i-1得到的若干子串都是满足回文的,但从i开始后面找不到了,那么此时遍历到主串末尾时就不能将这种分割方法添加到结果集里面去。只有每次分割位置得到的都是回文串时,遍历到主串末尾才能把这种分割方法添加到结果集;
    难点:
  1. 切割问题可以抽象为组合问题:即把主串分成连续的几大块
  2. 如何模拟那些切割线:用startIndex表示切割位置,即将startIndex-1及以前的部分跟后面隔开,尝试从以startIndex为后面那部分的起始位置去寻找回文串
    发、关于切割线的描述
  3. 切割问题中递归如何终止:分割到主串末尾(即startIndex >= s.size())
  4. 在递归循环中如何截取子串:
s.substr(int pos, int len); //得到主串s中以pos为第一个元素,长度为len的一个子串
  1. 如何判断一个字符串是不是回文:双指针
class Solution {
private:    
    vector<vector<string>> res;//结果集
    vector<string> path;//满足要求的一种分割方法,即分开的各个字串都是回文的

    bool ispalindrome (const string& str) {//用于判断str是否是回文的
        int len = str.size();
        if (len == 1) return true;
        for(int i = 0, j = len - 1; i <= j; ++i, --j) {
            if (str[i] != str[j]) return false;
        }
        return true;
    }
	//主串s将从[startIndex, s.size() - 1]去寻找分割方法 
    void backtracking (const string& s, int stratIndex) {//只有一个集合s,因此需要标记起始位置
        if (stratIndex >= s.size()) {//终止条件:分到达主串末尾
            res.push_back(path);
            return;
        }
        
        for(int i = stratIndex; i < s.size(); ++i) {//从startIndex开始遍历每个位置,都去尝试作为分割线
            string tmp = s.substr(stratIndex, i - stratIndex + 1);//尝试i位置作为分割线
            if (ispalindrome(tmp)) path.push_back(tmp);
            else continue;

            backtracking(s, i + 1);//递归

            path.pop_back();//回溯
        }
    }
public:
    vector<vector<string>> partition(string s) {
        backtracking(s, 0);

        return res;
    }
};
  • 总结:
  1. 切割问题可以抽象为组合问题;
  2. 切割问题用回溯;
  3. 通过传递参数为主串和int startIndex来模拟切割线;
当前切割位置为startIndex(startIndex前面可能已经经过多次切割了),startIndex只是说明最近的一次切割为此处,即将从startIndex开始往后寻找下一个切割位置;
  1. 终止条件为切割到主串末尾;
  2. 用substr函数来取子串;
string::substr(int pos, int len);
  1. 切割过的位置不能重复切割,因此必须传递i + 1而不能是i;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值