LeetCode(5)

动态规划

什么是动态规划?

一、基本概念
动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。

二、基本思想与策略
基本思想与分治法类似: 待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策 保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题的解就是初始问题的解。
由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次, 将其不同阶段的不同状态保存在一个二维数组中。
与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。

三、适用的情况
能采用动态规划求解的问题的一般要具有3个性质:
(1) 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。
(2) 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。
(3) 有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)

回到这个题 :
如12321是回文的话,那 2332 肯定也是回文。所以我们可以根据动态规划的两个特点:第一 : 问题由大拆小,第二重复利用之前的计算结果 . 来解答这道题。
1. 那如何划分小问题呢,我们先把所有长度为1的子串标记为回文: 即 dp[i][i] = 1 , 之后重复判断 :如果短串不是回文(如abc不是回文),那长串也不是(如vabcv也不会是回文 ) ; 如果短串是回文,那就要看长串两头是否一样 , 如果长串两头一样 , 那长串必然是回文 , 这样,一直到长度最大的子串,我们就把整个字符串集穷举完了。
2. 重复利用的方法就是 : 如果 串 x’aba’y 的两边 x == y , 那么把子串 aba 的 dp 值 赋给 主串 . 即 : dp(主串) = dp (子串) .. ‘aba’ 的 dp 值是true , 那么这个主串也就相应的是回文串 , 倘若子串的 dp 值是 false(如 abc ) , 就算你主串的 x == y ,那你也不可能是回文串了 . ( 如xabcx )
3. 至于 “bb” 这类特殊问题 . 我们在写的时候讨论一下就可以了

下面是AC代码 , dp[i][j] 的 i 代表 串的起始下标 , j 代表结束下标 , 比如 str = “abcd” , dp[1][2] 代表这个子串从第str(1)开始 , 到str(2)结束 , 也就是 “bc” .. 如果表示一个字符 , 那就是 dp[i][i]

class Solution {
public:
string longestPalindrome(string s) {
    int maxLength = 0;
    int maxStart = 0;
    int len = s.length();
    bool dp[len][len] ;
    for(int i = 0; i < len; i++)
        for(int j = 0; j < len; j++)
            dp[i][j] = 0;

    // l 表示字符串长度, l = len的时候遍历结束
    for(int le = 0; le < len; le++) {
        // i 是字符串起始位置
        for(int i = 0; i < len - le ; i++) {
            if( le == 0 ) {   //长度为 0 ,所有单字符回文
                dp[i][i+le] = 1;
            } else if(le==1 && s.at(i) == s.at(i+1)) {
                //处理 l==1 ,也就是"aa" 的这种情况 .
                dp[i][i+1] = 1;
            } else if (le!=1 && s.at(i) == s.at(i+le) ) 
                dp[i][i+le] = dp[i+1][i+le-1];
            else {dp[i][i+le] = false; } 

            if(dp[i][i+le]==true && le >= maxLength) {
                maxLength = le + 1 ;
                maxStart = i;  
            }
        } 
    }
    return s.substr(maxStart, maxLength );
    } 
};
int main() {
    Solution aa;
    string s = aa.longestPalindrome("ababab");
    cout<<"主函数输出 :"<<s<<endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值