【leetcode】LCP 19. 秋叶收藏集(UlBDOe)(DP)[中等]

    科技2022-07-10  86

    链接

    https://leetcode-cn.com/problems/UlBDOe/

    耗时

    解题:3 h 15 min 题解:58 min

    题意

    小扣出去秋游,途中收集了一些红叶和黄叶,他利用这些叶子初步整理了一份秋叶收藏集 leaves, 字符串 leaves 仅包含小写字符 r 和 y, 其中字符 r 表示一片红叶,字符 y 表示一片黄叶。 出于美观整齐的考虑,小扣想要将收藏集中树叶的排列调整成「红、黄、红」三部分。每部分树叶数量可以不相等,但均需大于等于 1。每次调整操作,小扣可以将一片红叶替换成黄叶或者将一片黄叶替换成红叶。请问小扣最少需要多少次调整操作才能将秋叶收藏集调整完毕。

    思路

    这是之前 leetcode 一个 CUP 的题,比赛时没做出来,当时想用贪心,后来看答案才想 DP。由于之前看过答案,自己也没有思路,所以这是照答案的思路写的。

    三个一维 dp, dp[0][:] 是字符串的字符的排列调整成「红」一部分,即都换成 r 需要调整多少次; dp[1][:] 是字符串的字符的排列调整成「红、黄」二部分,即换成 rrrr…yyy 最少需要调整多少次; dp[2][:] 是字符串的字符的排列调整成「红、黄、红」三部分,即换成 rrrrr…yyy…rrrr 最少需要调整多少次;

    dp[0][i] 非常简单,直接看 leaves[i] 是不是 r 就行了; dp[1][i] 就有两种情况了,…,两种情况取最小

    1. 从 dp[0][i-1] 全是 r 的转移过来,变成 rrrr...rrrry 2. 从 上一个状态 dp[1][i-1] 转移过来,变成 rrrr...rrrry..y

    dp[2][i] 和 dp[1][i] 差不多,

    1. 从 dp[1][i-1] 转移过来,变成 rrrr...rrrry..yr 2. 从 上一个状态 dp[2][i-1] 转移过来,变成 rrrr...rrrryyyy...yyyyr..r

    状态转移方程: { d p [ 0 ] [ i ] = d p [ 0 ] [ i − 1 ] + 1 l e a v e s [ i ] = = ′ r ′ d p [ 1 ] [ i ] = m i n ( d p [ 0 ] [ i − 1 ] , d p [ 1 ] [ i − 1 ] ) + 1 l e a v e s [ i ] = = ′ y ′ d p [ 2 ] [ i ] = m i n ( d p [ 1 ] [ i − 1 ] , d p [ 2 ] [ i − 1 ] ) + 1 l e a v e s [ i ] = = ′ r ′ \begin{cases} dp[0][i] = dp[0][i-1] + 1^{leaves[i]=='r'} \\ dp[1][i] = min(dp[0][i-1], dp[1][i-1]) + 1^{leaves[i]=='y'} \\ dp[2][i] = min(dp[1][i-1], dp[2][i-1]) + 1^{leaves[i]=='r'} \end{cases} dp[0][i]=dp[0][i1]+1leaves[i]==rdp[1][i]=min(dp[0][i1],dp[1][i1])+1leaves[i]==ydp[2][i]=min(dp[1][i1],dp[2][i1])+1leaves[i]==r

    时间复杂度: O ( n ) O(n) O(n)

    AC代码

    class Solution { public: int minimumOperations(string leaves) { int n = leaves.size(); vector<vector<int>> dp(3, vector<int>(n+1, 0)); dp[0][1] = dp[2][1] = dp[1][1] = (leaves[0]=='r'?0:1); dp[2][2] = dp[1][2] = dp[1][1] + (leaves[1]=='y'?0:1); dp[0][2] = dp[0][1] + (leaves[1]=='r'?0:1); for(int i = 3; i <= n; ++i) { dp[0][i] = dp[0][i-1] + (leaves[i-1]=='r'?0:1); dp[1][i] = min(dp[0][i-1], dp[1][i-1]) + (leaves[i-1]=='y'?0:1); dp[2][i] = min(dp[1][i-1], dp[2][i-1]) + (leaves[i-1]=='r'?0:1); } return dp[2][n]; } };
    Processed: 0.065, SQL: 8