• 代码随想录Day_57打卡


    ①、回文子串

    给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

    回文字符串 是正着读和倒过来读一样的字符串。

    子字符串 是字符串中的由连续字符组成的一个序列。

    具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

    事例:

    输入:s = "abc"
    输出:3
    解释:三个回文子串: "a", "b", "c"

    思路:

            使用动态规划,dp为二维数组,以第一二维切割字符串。如dp[i][j]表示字符串s下标从i到j是否为回文字串,统计所有dp[i][j]为true的个数。

    动态规划:

            dp定义及含义:dp[i][j]表示字符串s下标从i到j是否为回文字串

            状态转移方程:如果s[i] == s[j]的话,若中间为回文字串,则dp[i][j] = true,考虑到j一定大于i,故分为两种情况,若j - i <= 1或者 dp[i + 1][j - 1],则dp[i][j] = true。

            以dp视图来看,dp依赖于左下角赋值,故遍历顺序需先计算左下角。

            遍历顺序:先从大到小遍历s,再从小到大遍历,j依赖于i

            最终输出统计个数res

    代码:

    1. public int countSubstrings(String s) {
    2. int res = 0;
    3. boolean[][] dp = new boolean[s.length()][s.length()];
    4. for(int i = s.length() - 1;i >= 0;i--){
    5. for(int j = i;j < s.length();j++){
    6. if(s.charAt(i) == s.charAt(j)){
    7. if(j - i <= 1){
    8. res++;
    9. dp[i][j] = true;
    10. }else{
    11. if(dp[i + 1][j - 1]){
    12. dp[i][j] = true;
    13. res++;
    14. }
    15. }
    16. }
    17. }
    18. }
    19. return res;
    20. }

    ②、最长回文子序列

    给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

    子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

    事例:

    输入:s = "bbbab"
    输出:4
    解释:一个可能的最长回文子序列为 "bbbb" 。

    思路:

            切割跟上题类似,使用动态规划。dp[i][j]表示字符串s下标从i到j的最长回文子序列长度。若s[i] == s[j],则说明回文长度可以加上2,dp[i][j] = dp[i + 1][j - 1] + 2,若不能同时使用这两字符,则dp[i][j] = Math.max(dp[i + 1][j],dp[i][j - 1])。

    动态规划:

            dp定义及含义:dp[i][j]表示字符串s下标从i到j的最长回文子序列长度

            状态转移方程:if(s[i] == s[j]) dp[i][j] = dp[i + 1][j - 1] + 2

                                    else dp[i][j] = Math.max(dp[i + 1][j],dp[i][j - 1])

            初始化:dp[i][i] = 1,因为这样切割只有一个字符,算回文字符串

            遍历顺序:与上题一样,先从大到小遍历,再嵌套从小到大遍历

            dp[0][s.length() - 1]即为答案。

    代码:

    1. public int longestPalindromeSubseq(String s) {
    2. int[][] dp = new int[s.length()][s.length()];
    3. for(int i = 0;i < s.length();i++){
    4. dp[i][i] = 1;
    5. }
    6. for(int i = s.length() - 1;i >= 0;i--){
    7. for(int j = i + 1;j < s.length();j++){
    8. if(s.charAt(i) == s.charAt(j)){
    9. dp[i][j] = dp[i + 1][j - 1] + 2;
    10. }else{
    11. dp[i][j] = Math.max(dp[i + 1][j],dp[i][j - 1]);
    12. }
    13. }
    14. }
    15. return dp[0][s.length() - 1];
    16. }

    参考:代码随想录 (programmercarl.com)

  • 相关阅读:
    敏捷项目管理中产品负责人– PO的核心职责
    Jmeter响应时间和tps监听器使用教程
    循环队列基本知识与代码
    【Unity】【VRTK】【VR开发】同时保持高效打包和调试的VRTK项目设置方式
    30:第三章:开发通行证服务:13:开发【更改/完善用户信息,接口】;(使用***BO类承接参数,并使用了参数校验)
    【NodeJs篇】http模块
    SpringCloud Alibaba整合Ribbon负载均衡
    flutter系列之:flutter中常用的Stack layout详解
    MATLAB算法实战应用案例精讲-【数模应用】随机梯度下降法(SGD)(附Python、R语言、MATLAB和C++代码)
    Hive参数与性能企业级调优
  • 原文地址:https://blog.csdn.net/kk_try_hard/article/details/132745522