代码随想录第二十六天|动态规划(10)

目录

LeetCode 647. 回文子串

LeetCode 516. 最长回文子序列

总结


LeetCode 647. 回文子串

题目链接:LeetCode 647. 回文子串

思想:还是动归五部曲吧,先考虑dp数组的含义。dp[i][j]标明的是s的子串区间[i,j]如果是回文串的话,其值为true。不然就为false。其实这一点十分聪明,可以省掉单独对回文串的判断,因为一个回文串的确定可以由他去掉两边相同的字母的子串确定。也就是说,如果一个子串[i,j],其中s[i]==s[j],且子窜[i+1,j-1]是回文子串的话,那么[i,j]也是回文子串。第二个就是递推公式了,分为两种情况,第一种情况s[i]!=s[j],那么dp[i][j]=false。第二种情况s[i]==s[j],这时候又可以分为两种情况,当j-1<=1的时候,即子串是由一位或两位组成的时候,让dp[i][j]=true,并让记录结果的数据+1;当j-1>1的时候,这个时候判断区间[i+1][j-1]是否是回文子串,也就是查看dp[i+1][j-1]的值,如果是true,让dp[i][j]=true,并让记录结果的数据+1。初始化将全部数据先初始化为false,如果有需要的话也可以将dp[i][i]初始化为true。然后需要确认遍历顺序,根据递推公式来看,dp[i][j]需要dp[i+1][j-1]来确定,也就是说需要从下往上,从左往右遍历。

代码如下:

    int countSubstrings(string s) {
        vector<vector<bool>> dp(s.size(), vector<bool> (s.size(), false));
        int result = 0;
        for (int i = s.size() - 1; i >= 0; i--) {
            for (int j = i; j < s.size(); j++) {
                if (s[i] == s[j]) {
                    if (j - i <= 1) {
                        result++;
                        dp[i][j] = true;
                    }else if (dp[i+1][j-1]) {
                        result++;
                        dp[i][j] = true;
                    }
                }
            }
        }
        return result;
    }

时间复杂度:O(n^2),空间复杂度:O(n^2)。

LeetCode 516. 最长回文子序列

题目链接:LeetCode 516. 最长回文子序列

思想:还是动归五部曲。首先是dp数组的含义,跟上题差不多。本题dp[i][j]是指[i,j]区间内最长的回文子序列长度。其次就是递推公式,还是分为两种情况,第一种是s[i]==s[j],那么dp[i][j]=dp[i+1][j-1]+2;第二种是s[i]!=s[j],此时需要考虑的区间就是[i+1,j]和[i,j-1]查看这两个区间的最长回文子串序列长度,并令dp[i][j]=max(dp[i][j-1],dp[i+1][j]);然后就是初始化,需要将单个字母为一个区间的dp数组初始化为1,因为单个字母就是一个回文串。然后遍历顺序就跟上题一模一样了。

代码如下:

    int longestPalindromeSubseq(string s) {
        vector<vector<int>> dp(s.size(), vector<int> (s.size(), 0));
        for (int i = 0; i < s.size(); i++) dp[i][i] = 1;
        for (int i = s.size() - 1; i >= 0; i--) {
            for (int j = i + 1; j < s.size(); j++) {
                if (s[i] == s[j]) {
                    dp[i][j] = dp[i+1][j-1]+2;
                } else {
                    dp[i][j] = max(dp[i][j-1], dp[i+1][j]);
                }
            }
        }
        return dp[0][s.size()-1];
    }

时间复杂度:O(n^2),空间复杂度:O(n^2)。

总结

动态规划这一章完了, 但是我感觉自己还是没咋提升。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值