【多维DP】力扣2370. 最长理想子序列

二维DP

csharp 复制代码
class Solution {
public:
    int longestIdealString(string s, int k) {
        int n = s.size();
        vector<vector<int>> dp(n, vector<int>(26));
        dp[0][s[0] - 'a'] = 1;
        for(int i = 1; i < n; i++){
            int currentChar = s[i] - 'a';
            for(int prevChar = max(0, currentChar - k); prevChar <= min(25, currentChar + k); prevChar++){
                dp[i][currentChar] = max(dp[i][currentChar], dp[i-1][prevChar] + 1);
            }
            dp[i][currentChar] = max(dp[i][currentChar], 1);

            for(int j = 0; j < 26; j++){
                dp[i][j] = max(dp[i][j], dp[i-1][j]);
            }
        }
        int ans = 0;
        for(int c = 0; c <= 25; c++){
            ans = max(ans, dp[n-1][c]);
        }
        return ans;
    }
};

时间复杂度:O(Nk)
空间复杂度:O(Nk)

对于子序列题目,我们通常可以定义一个二维数组dpic用来表示在s的前i个字符(i从0开始)并且以c字符作为结尾的最长理想子序列。

我们定义完dp后,首先对dp进行初始化:dp[0][s[0] - 'a'] = 1;,代表s0自身作为子序列的长度为1。接下来我们遍历i从1到n,我们首先假设字符串s的si为目前最长理想子序列的结尾,那么他可以由dp[i][currentChar] = max(dp[i][currentChar], dp[i-1][prevChar] + 1);也就是可以从上一个状态i-1的所有可能的prevChar进行状态转移而来。

如果currentChar无法从任何一个prevChar进行状态转移而来,那么我们就令他为自身长度1,也就是 dp[i][currentChar] = max(dp[i][currentChar], 1);

最后假设我们不以si作为结尾,那么当前的状态dpij则要继承上一个状态的dpi-1j

我们定义一个变量ans,用来记录s的前n个(即全部)字符并且以任何字符为结尾的理想子序列的最大值,并返回。


空间压缩

csharp 复制代码
class Solution {
public:
    int longestIdealString(string s, int k) {
        int n = s.size();
        vector<int> dp(26);
        
        for(char c : s){
            int maxLen = 0;
            int curChar = c - 'a';
            for(int prevChar = max(0,curChar - k); prevChar <= min(25, curChar + k); prevChar++){
                maxLen = max(maxLen, dp[prevChar]);
            }
            dp[curChar] = maxLen + 1;
        }
        return *max_element(dp.begin(), dp.end());
    }
};

空间复杂度压缩至O(1)

由于观察状态转移方程i都是由上一个状态i-1状态转移而来,那么我们可以采用滚动的方式进行空间压缩,我们定义dpc为以字符c为结尾的最长理想子序列的长度,并且而外定义一个变量maxLen来记录被转移状态的最长理想子序列的长度,所以当前的最长理想子序列长度就是dp[curChar] = maxLen + 1;

相关推荐
Sw1zzle30 分钟前
算法入门(四):二叉树 - 递归遍历三件套
算法·leetcode
万法若空1 小时前
【算法-查找】查找算法
java·数据结构·算法
海石1 小时前
子树怎么找?树的3种遍历方式来帮忙!
算法·leetcode
海石1 小时前
难度分 1588:思路 + 技巧 = AC
算法·leetcode
珠海西格电力5 小时前
云边端协同架构:零碳园区管理系统的技术底座
大数据·运维·人工智能·算法·架构·能源
还有多久拿退休金6 小时前
让飞书知识库跟着 commit 自己长:一套自动化知识库的真实实现
前端·算法·架构
KaMeidebaby8 小时前
卡梅德生物技术快报|小 RNA 适配体合成 + 多方法亲和力表征全流程标准化操作手册
前端·网络·数据库·人工智能·算法
是Dream呀8 小时前
基于深度学习的人类行为识别算法研究
人工智能·深度学习·算法
happyprince9 小时前
03_NVIDIA_ModelOpt-量化算法深入
人工智能·深度学习·算法
大鱼>9 小时前
AI+货物追踪:智能快递柜追踪系统
人工智能·深度学习·算法·机器学习