leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记

这篇具有很好参考价值的文章主要介绍了leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

我的往期文章:

leetCode 647.回文子串 动态规划 + 优化空间 / 中心扩展法 + 双指针-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/133883091?spm=1001.2014.3001.5501leetCode 131.分割回文串 + 回溯算法 + 图解 + 笔记-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/134700907?spm=1001.2014.3001.5501(一)利用动态规划来优化判断回文子串

  • 利用动态规划高效地事先一次性计算出, 针对一个字符串s, 它的任何子串是否是回文字串, 然后在我们的回溯函数中直接查询即可, 省去了双指针移动判定这一步骤.(来自代码随想录Carl老师的原话)原文链接:代码随想录 (programmercarl.com)

>>思路和分析

回文子串:讲究的是这个字符串里边左右两边是对称的左右两边的元素是相同的。如果只判断这个字符串的最左面和最右面这两个元素相同的情况下,还知道中间的子串已经是回文的,那么就可以直接判断整个字符串它就是回文子串。

leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记,回溯算法,动态规划,算法,leetcode,笔记,回溯算法,动态规划,优化,图解

也就是说,如果在[i+1,j-1]范围的子串是一个回文串,再向两边拓展遍历的时候,那只需要判断两边这两个元素是否相同就可以了若相同,dp[i][j]是回文串

>>动规五部曲

1.确定dp数组以及下标的含义

  • dp[i][j]:表示区间范围[i,j]的子串是否为回文子串。如果是,则dp[i][j] = true,否则为false
  • 或者说,dp[i][j] 表示截取从 i 到 j 的子串是否为回文子串

2.确定递推式

if(j == i) dp[i][j]=true;
else if(j-i == 1) dp[i][j] = (s[i]==s[j]);
else dp[i][j] = (s[i] == s[j] && dp[i+1][j-1]);

3.dp 数组初始化

  • dp[i][j]初始化为false

4.确定遍历顺序

一定要从下到上,从左到右遍历,这样能保证dp[i+1][j-1]是经过计算得来的

leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记,回溯算法,动态规划,算法,leetcode,笔记,回溯算法,动态规划,优化,图解

 5.举例推导dp数组leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记,回溯算法,动态规划,算法,leetcode,笔记,回溯算法,动态规划,优化,图解

void computePalindrome(const string& s) {
    // dp[i][j] 代表s[i:j](双边包括)是否是回文子串
    dp.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) dp[i][j]=true;
            else if(j-i == 1) dp[i][j] = (s[i]==s[j]);
            else dp[i][j] = (s[i] == s[j] && dp[i+1][j-1]);
        }
    }
}
"aebeaeccfcce"
1  0  0  0  1  0  0  0  0  0  0  0  
0  1  0  1  0  0  0  0  0  0  0  0  
0  0  1  0  0  0  0  0  0  0  0  0  
0  0  0  1  0  1  0  0  0  0  0  0  
0  0  0  0  1  0  0  0  0  0  0  0  
0  0  0  0  0  1  0  0  0  0  0  1  
0  0  0  0  0  0  1  1  0  0  1  0  
0  0  0  0  0  0  0  1  0  1  0  0  
0  0  0  0  0  0  0  0  1  0  0  0  
0  0  0  0  0  0  0  0  0  1  1  0  
0  0  0  0  0  0  0  0  0  0  1  0  
0  0  0  0  0  0  0  0  0  0  0  1  


"acgcabbfcc"
1  0  0  0  1  0  0  0  0  0  
0  1  0  1  0  0  0  0  0  0  
0  0  1  0  0  0  0  0  0  0  
0  0  0  1  0  0  0  0  0  0  
0  0  0  0  1  0  0  0  0  0  
0  0  0  0  0  1  1  0  0  0  
0  0  0  0  0  0  1  0  0  0  
0  0  0  0  0  0  0  1  0  0  
0  0  0  0  0  0  0  0  1  1  
0  0  0  0  0  0  0  0  0  1  

(二)分割回文串 + 动态规划 + 回溯算法 + 优化

class Solution {
public:
    vector<vector<string>> result;
    vector<string> path; // 放已经回文的子串
    vector<vector<bool>> dp; // 放事先计算好的是否回文子串的结果
    void backtracking(const string& s,int startIndex) {
        // 如果起始位置已经大于 s 的大小,说明已经找到了一组分割方案了
        if(startIndex >= s.size()) {
            result.push_back(path);
            return;
        }
        for(int i=startIndex;i<s.size();i++) {
            if(dp[startIndex][i]) { // 是回文子串
                // 获取[startIndex,i] 在 s 中的子串
                string subStr = s.substr(startIndex,i-startIndex+1);
                path.push_back(subStr);
            }else continue; // 不是回文,跳过
            backtracking(s,i+1);// 寻找 i+1 为起始位置的子串
            path.pop_back();// 回溯过程,弹出本次已经添加的子串
        }
    }
    void computePalindrome(const string& s) {
        // dp[i][j] 代表s[i:j](双边包括)是否是回文子串
        dp.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) dp[i][j]=true;
                else if(j-i == 1) dp[i][j] = (s[i]==s[j]);
                else dp[i][j] = (s[i] == s[j] && dp[i+1][j-1]);
            }
        }
    }
    vector<vector<string>> partition(string s) {
        computePalindrome(s);
        backtracking(s, 0);
        return result;
    }
};

参考和推荐文章:

代码随想录 (programmercarl.com)https://www.programmercarl.com/0131.%E5%88%86%E5%89%B2%E5%9B%9E%E6%96%87%E4%B8%B2.html#%E6%80%9D%E8%B7%AF

摘选代码随想录的总结:

  • 总结难点:
  1. 如何切割?切割问题可以抽象为组合问题
  2. 如何模拟那些切割线?
  3. 切割问题中递归如何终止?
  4. 在递归循环中如何截取子串?
  5. 如何判断回文?

递归用于纵向遍历,for循环用于横向遍历当切割线迭代至字符串末尾,说明找到一种方法。类似组合问题,为了不重复切割同一位置,利用 start_index 作为标记,记录下一轮。递归的起始位置(切割线)。切割过的地方不能重复切割,故递归函数传入 i+1文章来源地址https://www.toymoban.com/news/detail-753521.html

到了这里,关于leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【刷题1】LeetCode 131. 分割回文串 java题解

    2024: 刚开始做leetcode hot100,查阅自己以前写的题解专栏,发现没有这一题,于是加上。可能leetcode100更新了吧。我看现在leetcode100官网的题目已经是分好类的了,以前我的题解帖子是自己手动分类整理的。

    2024年02月19日
    浏览(42)
  • (动态规划) 132. 分割回文串 II ——【Leetcode每日一题】

    难度:困难 给你一个字符串 s ,请你将 s 分割成一些子串,使每个子串都是回文。 返回符合要求的 最少分割次数 。 示例 1: 输入:s = “aab” 输出:1 解释:只需一次分割就可将 s 分割成 [“aa”,“b”] 这样两个回文子串。 示例 2: 输入:s = “a” 输出:0 示例 3: 输入:

    2024年02月15日
    浏览(46)
  • 【算法|动态规划No30】leetcode5. 最长回文子串

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助 🍓希望我们一起努力、成长,共同进步。

    2024年02月08日
    浏览(41)
  • 算法打卡day49|动态规划篇17| Leetcode 647. 回文子串、516.最长回文子序列

    Leetcode 647. 回文子串 题目链接:647. 回文子串 大佬视频讲解:647. 回文子串视频讲解  个人思路  这道题的dp数组有点难找到关联,以至于递归关系也不好找,所以看题解吧... 解法 动态规划 动规五部曲: 1.确定dp数组(dp table)以及下标的含义 一般在定义dp数组的时候 会根据题

    2024年04月22日
    浏览(50)
  • 【算法|动态规划No.28】leetcode1312. 让字符串成为回文串的最少插入次数

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助 🍓希望我们一起努力、成长,共同进步。

    2024年02月06日
    浏览(57)
  • C++力扣题目131--分割回文串

    131. 分割回文串 给你一个字符串  s ,请你将   s   分割成一些子串,使每个子串都是  回文串  。返回  s  所有可能的分割方案。 回文串  是正着读和反着读都一样的字符串。 示例 1: 示例 2: 提示: 1 = s.length = 16 s  仅由小写英文字母组成 本题这涉及到两个关键问题:

    2024年01月20日
    浏览(37)
  • 动态规划-分割回文串 II

    跟着九章侯老师学习了动态规划专题之后根据学习所总结: 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。 返回符合要求的 最少分割次数 。 输入:s = “aab” 输出:1 解释:只需一次分割就可将 s 分割成 [“aa”,“b”] 这样两个回文子串。 输入:s = “

    2024年02月10日
    浏览(48)
  • 【动态规划】【字符串】132.分割回文串 II

    视频算法专题 动态规划汇总 字符串 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。 返回符合要求的 最少分割次数 。 示例 1: 输入:s = “aab” 输出:1 解释:只需一次分割就可将 s 分割成 [“aa”,“b”] 这样两个回文子串。 示例 2: 输入:s = “a”

    2024年02月03日
    浏览(53)
  • 【力扣】416. 分割等和子集 <动态规划、回溯>

    给你一个 只包含正整数的非空数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 示例 1: 输入:nums = [1,5,11,5] 输出:true 解释:数组可以分割成 [1, 5, 5] 和 [11] 。 示例 2: 输入:nums = [1,2,3,5] 输出:false 解释:数组不能分割成两个元素和

    2024年02月10日
    浏览(39)
  • day27 | 39. 组合总和、 40.组合总和II、131.分割回文串

    目录: 39. 组合总和 给你一个  无重复元素  的整数数组  candidates  和一个目标整数  target  ,找出  candidates  中可以使数字和为目标数  target  的 所有 ** 不同组合  ,并以列表形式返回。你可以按  任意顺序  返回这些组合。 candidates  中的  同一个  数字可以  无限

    2024年02月10日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包