秋叶收藏集, LC个人竞赛题目解析

这道题目是lc竞赛的题目,记得是那次竞赛的第三题,当时发现这道题目是在B站上,看见有人分享这道题目,自己当时没看懂,后来特意百度了一下,看懂了。今天的LC 每日一题就是这道题目,感觉这道题目和我非常有缘,另外是一道很有意思的DP题目,所以写下这篇博客记录一下。

题目

将收藏集中树叶的排列调整成「红、黄、红」三部分。每部分树叶数量可以不相等,但均需大于等于 1。每次调整操作,小扣可以将一片红叶替换成黄叶或者将一片黄叶替换成红叶。请问小扣最少需要多少次调整操作才能将秋叶收藏集调整完毕。

动态规划是压缩空间以及时间的递推过程嘛,但是常常想不到,我认为有两个点非常重要:

  • 这个这个递推过程中有那些递推状态!!
  • 关于递推过程的递推公式应该如何书写!!
    前一个点往往是后一个点的前提,因为如果我们遇到一个动态规划的时候,连递推过程的状态我们都理不清,那么怎么可能理的清递推公式呢?

首先我们先构建一下dptable,这个dptable 的大小是3*n(n 是我们需要判断的那个序列的长度大小),

  • (dp[0][i])标识到索引为i的位置,序列全为红需要经过多少次调整。
  • (dp[1][i])标识到索引为i的位置,序列为红 + 黄 需要经过多少次调整
  • (dp[2][i])标识到索引为i的位置,序列为红 + 黄 + 红需要经过多少次调整
    那么接下来就比较简单了:
  • 序列为 红 + 黄,这种状态需要参考前一个状态下的 红 + 黄以及前一个状态下的 全为红 这种情况,然后做递推
  • 序列为 红 + 黄 + 红,这种状态需要参考前一个状态下的红 + 黄 以及前一个状态下的红 + 黄 + 红这种情况, 然后做递推

这里需要注意的还是边界条件,比如在第一次判断 红 + 黄这种第一次判断的时候索引必然是 >= 1,因为 至少一个红一个黄
此外第一次判断 红+黄+红的时候,索引必然是 >= 2, 因为至少两个红加一个黄。所以边界条件要做好~ 好了这就是我所有的分析,懒得打公式了,如果需要看递推公式,直接看代码吧~

最后, 国庆中秋双节快乐呀~

class Solution {
public:
    int minimumOperations(string leaves) {
        int n = leaves.size();
        // [r, y, r] 红 黄 红 三个颜色
        vector<vector<int>> dp(3, vector<int>(n , 0));
        dp[0][0] = leaves[0] == 'r'? 0:1;
        dp[1][0] = INT_MAX;
        dp[2][0] = INT_MAX;
        dp[2][1] = INT_MAX; 
        for(int i = 1; i < n; i++){
            int isyellow = leaves[i] == 'y'? 1:0;
            int isred = leaves[i] == 'r'? 1:0;
            dp[0][i] = dp[0][i-1] + isyellow; // 维持整个序列全是红色需要多少次调整
            dp[1][i] = min (dp[1][i-1], dp[0][i-1]) + isred; // 维持整个序列是红色 + 黄色需要多少次调整
            if ( i >= 2)
                dp[2][i] = min (dp[1][i-1], dp[2][i-1]) + isyellow; // 维持整个序列是红色 + 黄色 + 红色需要调整多少次, 但是我们做dp 只是利用当前数值对状态进行扩展
                                                                    // 在扩展的时候我们要注意我们前提,就是我们的前状态需要至少有两个序列,这样才能保证我们这个状态至少有三个序列
                                                                    // 才可能构成 红黄红这种序列情况
        }
        return dp[2][n-1];

    }
};
原文地址:https://www.cnblogs.com/wsl-hitsz/p/13757996.html