动态规划 回文篇

本文详细梳理了LeetCode中关于回文串的题目,包括LC5最长回文子串、LC9回文数、LC131分割回文串i和LC132分割回文串ii。介绍了回文串的概念,并通过动态规划和记忆化搜索的方法解决相关问题,还探讨了递归回溯在解题中的应用。

LeetCode刷题最好按照标签归类来刷,本文主要对leetcode上的回文串问题做一个梳理。
Leetcode上回文串经典题如下:

  1. LC5. 最长回文子串
  2. LC9. 回文数
  3. LC131.分割回文串i
  4. LC132.分割回文串ii

回文串核心问题

什么是回文串

回文字符串指的是字符串从左到右 和从右到左是一样的。

  1. 单个字符肯定是回文串
  2. 两个字符如果相等是回文串
  3. 多个字符,如果首末位相等,中间是回文,那么整体是回文

概括三种情况:
对于一个字符串s,从下标i到j的子串,判断其回文。flag[i][j]表示i~j是否为回文。

s[i]==s[j] &&(flag[i+1][j-1] || j-i<=1)

依赖关系
由此可见flag[i][j]依赖于flag[i+1][j-1],我们要计算出flag[i][j]必须先求出flag[i+1][j-1],而这个位置是在(i,j)的下方,因此我们填充flag这个表格数组的时候遵从的是从左到右从下到上的生成方式。

LC5 最长回文子串

使用动态规划 dp[i] 表示从i到len-1位置的最长回文子串长度。
图1 最长回文子串演示
求出一个dp数组,保存[i,j]是否为回文的信息,对于一个从i到j的子串,如何判断它是否为回文串。
如图1,当固定i=3时,j可以从3到7进行遍历,每次j遍历的过程中会计算出i到j是否是回文,这样再下次计算的时候,直接使用,不用重复计算。
如当i=3,j=5时,s[i]=s[j],且flag[4][4]是true,那么dp[i]此时就可以进行更新,dp[i]=5-3+1=3;当j不断向后继续遍历,dp[i]的值就会不断更新。

	/**
	**为什么不能从i=0到i=n-1 而是要从i=n-1到i=0因
    **flag[i][j]依赖于 flag[i+1][j-1]因此 要先计算出i+1行 ,j-1列才能推算		出i,j
   **因此方向为从下到上,从左到右
   **/
    public String longestPalindrome(String s) {
   
   
        if(s==null || s.length()==0){
   
   
            return "";
        }
        int n=s.length();
        boolean[][] flag=new boolean[n][n];
        int[] dp=new int[n];
        for(int i=0;i<n;i++){
   
   
            dp[i]=1;
        }
        char[]t =s.toCharArray();
        //记录长度
        int res=0;
        //记录起始位置
        int index=-1;
        for(int i=n-1;i>=0;i--){
   
   
            for(int j=i;j<n;j++){
   
   
                //[i,j]是回文,dp[i]表示[i,len-1]上的最长回文串,dp[i]有一个初始值
                //现在找到了一个 i~j 长度为j-i+1,  j一直变化,能够找到以i开头的最大长度
                if(t[i]==t[j]&& (j-i<=1||flag[i+1][j-1])){
   
   
                    flag[i][j]=true;
                    //从i到j是回文,那么[i,len-1]的最长回文 至少有j-i+1;
                    dp[i]=Math.max(dp[i],j-i+1);
                }
            }
            if(res<dp[i]){
   
   
                res=dp[i];
                index=i;
            }
        }
        return s.substring
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值