首页 > 编程语言 >算法力扣刷题记录 六十八【131.分割回文串】

算法力扣刷题记录 六十八【131.分割回文串】

时间:2024-08-07 12:59:26浏览次数:14  
标签:string temp sstr 131 力扣 startindex 六十八 回文 size

前言

回溯章节第六篇。切割问题。

记录 六十八【131.分割回文串】。


一、题目阅读

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

示例 1:

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

示例 2:

输入:s = "a"
输出:[["a"]]

提示:

1 <= s.length <= 16
s 仅由小写英文字母组成

二、尝试实现

思路

  1. 分析题目:输出结果元素是一种完整的分割方案。和字符串章节找回文串有区别
  2. 记录 六十三【回溯章节开篇】中说切割问题也是用回溯解决。并且回溯一定可以构造树形结构,从树形结构,结合前五篇解决组合问题的经验入手。
  3. 以示例1建立树形结构,宽度是字符串的分割点,深度是字符串的长度
    在这里插入图片描述
  4. 对照树形结构写递归函数:
  • 确定返回值:肯定是void类型;
  • 确定参数:
    • int startindex 代表每一层可选分割点的起始位置。类似组合问题中的startindex,每一层从哪些元素中开始选取;比如:startindex=0,指s[0]字符后的分割点;startindex = 1,指s[1]字符后的分割点。
    • string& s 代表输入的字符串。
  • 确定终止条件:当startindex == s.size()代表字符串已经分割结尾时,把temp放入result中,return;
  • 确定单层逻辑:
    • for循环:i从startindex开始,i指定某个下标后的分割点。传给下一层,应该从i+1开始。i < s.size();
    • 确定i之后,先把子串用s.substr函数返回。传入第一个参数是起始位置,第二个参数是长度。
    • 判断这个子串是回文串吗?用reverse反转之后比较是否相等。如果不是,continue,不再深入递归;如果是回文串,放到temp中,递到下一层。
    • 回溯操作:把该层放入temp的子串pop,进入下一轮i。

代码实现

class Solution {
public:
    vector<vector<string>> result;//最终的返回值
    vector<string> temp;//中间结果
    void backtracking(int startindex,string& s){
        //终止条件,一种分割方案完毕
        if(startindex == s.size()){
            result.push_back(temp);
            return;
        }

        //递归
        for(int i = startindex;i < s.size();i++){
            //获得子串
            string sstr = s.substr(startindex,i-startindex+1);//第一个参数是起始位置,第二参数是长度
            string r_sstr = sstr;
            reverse(r_sstr.begin(),r_sstr.end());
            if(sstr != r_sstr){//判断该子串是回文串吗?
                continue;//剪枝
            }

            temp.push_back(sstr);//放入该子串
            backtracking(i+1,s);//递到下一层
            temp.pop_back();//回溯
        }
        return;
    }
    vector<vector<string>> partition(string s) {
        result.clear();
        temp.clear();
        backtracking(0,s);
        return result;
    }
};

三、参考学习

参考学习链接

学习内容

  1. 使用回溯的思路是正确的。回溯使用特点:在一个集合中进行切割。
  2. 解决两个问题:1. 切割方案;2. 判断回文。参考代码实现和二、代码实现对比:
  • 细节一:递归函数参数string& s改成const string& s,为了不对s进行修改,一旦有修改操作会警告。
  • 细节二:终止条件——参考给startIndex >= s.size();个人写startIndex == s.size();这两个都可以。
  • 细节三:参考使用双指针另外写了一个函数调用来判断是否是回文串。而个人在reverse两行完成判断操作。
  1. 优化方法:用动态规划提前知道string s中的任何子串是否是回文串。没学到动态规划,但是先接触一下,从函数中分析动态规划的过程:

    void computePalindrome(const string& s) {
            // isPalindrome[i][j] 代表 s[i:j](双边包括)是否是回文字串 
            isPalindrome.resize(s.size(), vector<bool>(s.size(), false)); // 根据字符串s, 刷新布尔矩阵的大小
            for (int i = s.size() - 1; i >= 0; i--) { 
                // 需要倒序计算, 保证在i行时, i+1行已经计算好了
                for (int j = i; j < s.size(); j++) {
                    if (j == i) {isPalindrome[i][j] = true;}
                    else if (j - i == 1) {isPalindrome[i][j] = (s[i] == s[j]);}
                    else {isPalindrome[i][j] = (s[i] == s[j] && isPalindrome[i+1][j-1]);}
                }
            }
        }
    

    这是动态规划的函数。其中isPalindrome是二维矩阵,类型是:vector< vector< bool>>。如下图,一个举例。
    在这里插入图片描述


总结

在这里插入图片描述
(欢迎指正,转载标明出处)

标签:string,temp,sstr,131,力扣,startindex,六十八,回文,size
From: https://blog.csdn.net/danaaaa/article/details/140950913

相关文章

  • 力扣每日一题2024.8.5
    600.不含连续1的非负整数(困难)给定一个正整数n,请你统计在[0,n]范围的非负整数中,有多少个整数的二进制表示中不存在连续的1。示例1:输入:n=5输出:5解释:下面列出范围在[0,5]的非负整数与其对应的二进制表示:0:01:12:103:114:1005:101......
  • cockpit <=2.4.1 后台任意文件上传漏洞靶场复现(CVE-2023-1313)
    cockpit在2.4.1版本之前存在任意文件上传漏洞PS:通过在浏览器中打开/install来运行安装主页界面使用admin/admin登录不了根据提示访问/install后自动创建admin/admin,再次登录可以找到一个上传点,上传phpinfo并burp抓包具体路径可以在上传后有个下载按钮,会看到完整的访问......
  • leetcode力扣第29题:两数相除
    这题看似简单,实则一点也不难(不是),实则还是比较困难。最简单的做法是直接用减法,不停循环计数,最后统计减多少次能成。如果被除数是2^31-1或差不多大小的数,而除数是1差不多大小的数,那循环减法要执行的次数太多,一定会超时。所以一定要有更好的思路(1)通过二分法查找可能的商(2)对于......
  • day32【LeetCode力扣】541. 反转字符串 II
    day32【LeetCode力扣】541.反转字符串II1.题目描述给定一个字符串s和一个整数k,从字符串开头算起,每计数至2k个字符,就反转这2k字符中的前k个字符。如果剩余字符少于k个,则将剩余字符全部反转。如果剩余字符小于2k但大于或等于k个,则反转前k个字符,其余字符......
  • 【动态规划】力扣918. 环形子数组的最大和
    给定一个长度为n的环形整数数组nums,返回nums的非空子数组的最大可能和。环形数组意味着数组的末端将会与开头相连呈环状。形式上,nums[i]的下一个元素是nums[(i+1)%n],nums[i]的前一个元素是nums[(i-1+n)%n]。子数组最多只能包含固定缓冲区nu......
  • 134. 加油站【 力扣(LeetCode) 】
    一、题目描述  在一条环路上有n个加油站,其中第i个加油站有汽油gas[i]升。  你有一辆油箱容量无限的的汽车,从第i个加油站开往第i+1个加油站需要消耗汽油cost[i]升。你从其中的一个加油站出发,开始时油箱为空。  给定两个整数数组gas和cost,如果你可以......
  • 135. 分发糖果【 力扣(LeetCode) 】
    一、题目描述  n个孩子站成一排。给你一个整数数组ratings表示每个孩子的评分。  你需要按照以下要求,给这些孩子分发糖果:每个孩子至少分配到1个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。  请你给每个孩子分发糖果,计算并返回需要准备的最少糖果数......
  • 算法力扣刷题记录 六十四【216.组合总和III】
    前言回溯第二篇。回顾:上一篇学了回溯的基础知识和模版;组合练习题一应用了一次模版。本文继续组合问题练习:记录六十四【216.组合总和III】。一、题目阅读找出所有相加之和为n的k个数的组合,且满足下列条件:只使用数字1到9每个数字最多使用一次返回所有可能的有效......
  • 算法力扣刷题总结篇 ——【五】二叉树章节
    前言从记录三十五【二叉树基础和递归遍历】到记录六十二【538.把二叉搜索树转换为累加树】28篇文章都是二叉树的章节。所以总结的任务量有点大啊。但还是要做的。完成之后,开启新章节……继续。一、题目回顾1-5:遍历方式模版题。6-14:确定遍历顺序。后序居多——先统......
  • 【每日一题】【并查集】【力扣】695.岛屿的最大面积 C++
    力扣695.岛屿的最大面积695.岛屿的最大面积题目描述给你一个大小为m×nm\timesnm×n的二进制矩阵......