动态规划经典例题(最长回文子串)

回忆一下动态规划

我的理解就是动态规划实际上就是递推,他的时间复杂度一般比暴力法,递归法都要低,原因是因为动态规划是利用记忆好的历史数据,(不重复记忆)并使用

下面我将动态规划的算法思路,随解题过程来梳理回亿


题目描述

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:

输入:s = “cbbd”
输出:“bb”
示例 3:

输入:s = “a”
输出:“a”
示例 4:

输入:s = “ac”
输出:“a”

思路

1. 确定状态
判断某一子串是否为回文子串,我们以dp[i][j]来表示,从i~j这段子串,是否为回文子串(确定状态这一步需要经验(刷题数量),需要悟性)
2. 初始化
我们直到当只有一个字符时就是回文子串
for(int i=0;i<len;i++){
dp[i][i]=true;//初始化
}
3. 确定转移方程
确定转移方程我们一般由一个子问题来确定,且遵循后无效性原则
对于一个子串,若为回文子串,首先子串头与尾相同,依次以第n个与倒数第n个字符相同这种形式递推即可,
那么递推方程就显而易见了
dp[i][j]=dp[i+1][j-1];
4. 处理边界情况
当我们比对的子串只有2个或3个字符时
再进行i+1,j-1我们将会越界,所以我们需要处理边界情况
即当字符只有2个或3个时
只要满足
arr[i]==arr[j],dp[i][j]就为true
if(j-i<3){
dp[i][j]=true;
}

(最后设置一个最大值,截取这段最大值即可)

动态规划代码

class Solution {
    public String longestPalindrome(String s) {
    int len=s.length();
    char[] arr=s.toCharArray();
    boolean dp[][]=new boolean[len][len];//表示从第i个到第j个字符之间的字符串是否为回文子串
    //处理特殊情况
    if(len<=1){
        return s;
    }
    //初始化
    for(int i=0;i<len;i++){
        dp[i][i]=true;//自身与自身相等
    }
    int max=1;
    int begin=0;
    int end=0;
    for(int j=1;j<len;j++){
        for(int i=0;i<len-1&&i<j;i++){//注意处理下标之间的关系
            if(arr[i]!=arr[j]){
                dp[i][j]=false;
            }else{
                if(j-i<3){
                    dp[i][j]=true;
                }else{
                    dp[i][j]=dp[i+1][j-1];//如果i在外层,则i+1没有初始化,递推式不成立
                }
            }
            if(j-i+1>max && dp[i][j]){//还要满足状态对应
                max=j-i+1;
                begin=i;
                end=j;
            }
        }
    }
    return s.substring(begin,end+1);
    }
}

动态规划注意事项

在我们书写递推式的时候
dp[i][j]=dp[i+1][j-1]
我们应要考虑到i或j在for循环的里外层
如果i在外层,递推的时候dp[i+1]并未初始化,故应当将j放在外层

暴力代码

全排列再自定义函数传入判断

class Solution {
    public String longestPalindrome(String s) {
       int begin=0;
       int end=0;
       int maxlength=0;//初始化为1??
       
       char[] arr=s.toCharArray();
       if(arr.length<2){
           return s;
       }
       for(int i=0;i<arr.length;i++){//越界?
           for(int j=i+1;j<arr.length;j++){
               if(issubstring(arr,i,j)&&j-i+1>maxlength){
                   begin=i;
                   end=j;
                   maxlength=j-i+1;
               }
           }
       }
       return s.substring(begin,end+1);
    }
    private boolean issubstring(char[]arr,int begin,int end){
        while(begin<end){
            if(arr[begin]!=arr[end]){
                return false;
            }
            begin++;
            end--;
        }
        return true;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值