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

215 篇文章 0 订阅
26 篇文章 0 订阅

链接

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];
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值