当前位置:   article > 正文

leetCode 131.分割回文串 + 回溯算法 + 图解 + 笔记_分割回文串 力扣

分割回文串 力扣

131. 分割回文串 - 力扣(LeetCode)

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。回文串 是正着读和反着读都一样的字符串

示例 1:

  1. 输入:s = "aab"
  2. 输出:[["a","a","b"],["aa","b"]]

示例 2:

  1. 输入:s = "a"
  2. 输出:[["a"]]

>>思路和分析:

  1. 切割问题,有不同的切割方式
  2. 判断回文

代码随想录的Carl老师说:“切割问题类似组合问题”!(这段文字来自代码随想录--分割回文串

对于字符串abcdef

  • 组合问题选取一个a之后,在bcdef中再去选取第二个,选取b之后在cdef中再选取第三个.....
  • 切割问题切割一个a之后,在bcdef中再去切割第二段,切割b之后在cdef中再切割第三段.....

>>回溯三部曲:

1).确定回溯函数参数

  • path 存放切割后回文的子串
  • result 保存 path,作为结果集
  • startIndex 来控制for循环的起始位置(表示下一轮递归遍历的起始位置),还用来表示这条切割线.(切割过的地方,不能重复切割,和组合问题也是保持一致的【这句话来自代码随想录】)
  1. vector<vector<string>> result;
  2. vector<string> path; // 放已经回文的子串
  3. void backtracking (const string& s, int startIndex) // startIndex 就用来表示这条切割线

2).递归的终止条件

如果切割线切到了字符串最后面,表示找了一种切割方法,此时终止本层递归!也就是出现这种情况: startIndex >= s.size(),收集结果后直接return;

  1. void backtracking (const string& s, int startIndex) {
  2. // 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了
  3. if (startIndex >= s.size()) {
  4. result.push_back(path);
  5. return;
  6. }
  7. }

3).单层搜索的逻辑

>>问题(O_O)?思考:在递归循环中如何截取子串呢?

  • [startIndex,i]:左闭右闭,表示子串的起始位置和终止位置,有截取区间就可以截取子串。substr(startIndex, i - startIndex + 1);

>>问题(O_O)?思考:如何判断所截取子串是否为回文子串呢?

  1. 判断是否为回文子串:isPalindrome(s, startIndex, i),用双指针法
  2. 如果是回文,就加入在vector<string> path中,path 用来记录切割过的回文子串
  1. for (int i = startIndex; i < s.size(); i++) {
  2. if (isPalindrome(s, startIndex, i)) { // 是回文子串
  3. // 获取[startIndex,i]在s中的子串
  4. string str = s.substr(startIndex, i - startIndex + 1);
  5. path.push_back(str);
  6. } else { // 如果不是则直接跳过
  7. continue;
  8. }
  9. backtracking(s, i + 1); // 寻找i+1为起始位置的子串
  10. path.pop_back(); // 回溯过程,弹出本次已经添加的子串
  11. }

注意:切割过的位置,不能重复切割,应传入下一层的起始位置为 i + 1,即

  • backtracking(s, i + 1);

 (1)判断是否为回文子串

  1. bool isPalindrome(const string& s, int start, int end) {
  2. for (int i = start, j = end; i < j; i++, j--) {
  3. if (s[i] != s[j]) {
  4. return false;
  5. }
  6. }
  7. return true;
  8. }
  1. bool isPalindrome(string s) {
  2. int left = 0,right = s.size()-1;
  3. while(left<=right) {
  4. if (s[left] != s[right]) return false;
  5. left++;
  6. right--;
  7. }
  8. return true;
  9. }

 (2)C++代码

  1. class Solution {
  2. private:
  3. vector<vector<string>> result;
  4. vector<string> path; // 放已经回文的子串
  5. void backtracking (const string& s, int startIndex) {
  6. // 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了
  7. if (startIndex >= s.size()) {
  8. result.push_back(path);
  9. return;
  10. }
  11. for (int i = startIndex; i < s.size(); i++) {
  12. if (isPalindrome(s, startIndex, i)) { // 是回文子串
  13. // 获取[startIndex,i]在s中的子串
  14. string str = s.substr(startIndex, i - startIndex + 1);
  15. path.push_back(str);
  16. } else { // 不是回文,跳过
  17. continue;
  18. }
  19. backtracking(s, i + 1); // 寻找i+1为起始位置的子串
  20. path.pop_back(); // 回溯过程,弹出本次已经添加的子串
  21. }
  22. }
  23. bool isPalindrome(const string& s, int start, int end) {
  24. for (int i = start, j = end; i < j; i++, j--) {
  25. if (s[i] != s[j]) {
  26. return false;
  27. }
  28. }
  29. return true;
  30. }
  31. public:
  32. vector<vector<string>> partition(string s) {
  33. backtracking(s, 0);
  34. return result;
  35. }
  36. };
  • 时间复杂度: O(n * 2^n)
  • 空间复杂度: O(n^2)
  1. class Solution {
  2. public:
  3. vector<vector<string>> result;
  4. vector<string> path; // 放已经回文的子串
  5. bool isPalindrome(string s) {
  6. int left = 0,right = s.size()-1;
  7. while(left<=right) {
  8. if (s[left] != s[right]) return false;
  9. left++;
  10. right--;
  11. }
  12. return true;
  13. }
  14. void backtracking(string s,int startIndex) {
  15. // 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了
  16. if(startIndex >= s.size()) {
  17. result.push_back(path);
  18. return;
  19. }
  20. for(int i=startIndex;i<s.size();i++) {
  21. // 获取[startIndex,i]在s中的子串
  22. string subStr = s.substr(startIndex,i-startIndex+1);
  23. if(isPalindrome(subStr)) path.push_back(subStr);// 是回文子串
  24. else continue;// 不是回文,跳过
  25. backtracking(s, i + 1); // 寻找i+1为起始位置的子串
  26. path.pop_back(); // 回溯过程,弹出本次已经添加的子串
  27. }
  28. }
  29. vector<vector<string>> partition(string s) {
  30. backtracking(s, 0);
  31. return result;
  32. }
  33. };

 参考和推荐文章、视频:
带你学透回溯算法-分割回文串(对应力扣题目:131.分割回文串)| 回溯法精讲!_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1c54y1e7k6/?p=67&spm_id_from=pageDriver代码随想录 (programmercarl.com)icon-default.png?t=N7T8https://www.programmercarl.com/0131.%E5%88%86%E5%89%B2%E5%9B%9E%E6%96%87%E4%B8%B2.html#%E4%BC%98%E5%8C%96

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/676734
推荐阅读
相关标签
  

闽ICP备14008679号