【刷穿LeetCode系列】LCP 19.秋叶收集器 --- 动态规划题解

写在前面

大家好我是秋刀鱼,今天刷力扣时做了一道LCP的题目。有刷过LCP的小伙伴一定知道LCP题目向来都是不当人的难,中等难度基本上就碾压LeetCode中大部分困难题目。这道题解题思路非常巧妙,给大家分享一下。

LCP 19.秋叶收集器⭐️⭐️⭐️⭐️

题目传送门

【刷穿LeetCode系列】LCP 19.秋叶收集器 --- 动态规划题解_第1张图片

1、题目解析

题目要求的是将收集到的红叶、黄叶按照 【红、黄、红】的顺序整理为三个部分,每个部分至少有一片叶子。同时能够调整任意一片叶子的颜色。

不难得知,整理为下面的状态时,叶子的排列顺序符合题意:

【刷穿LeetCode系列】LCP 19.秋叶收集器 --- 动态规划题解_第2张图片

整理完毕后叶子的颜色排列一定是 红色黄色红色,不妨我们定义每片叶子所处的状态:

  • 状态一:处于开始的红色部分
  • 状态二:处于黄色部分
  • 状态三:处于结束的红色部分

现在每一片都有了自己的状态,同时每一片最终处于的状态都有可能是这三种状态之一。

但是为了满足题意,每一个颜色块的数量至少为1,也就是说最边缘叶子的状态我们是能够知道的,一定是红色的。

定义状态

定义数组 d p [ i ] [ j ] dp[i][j] dp[i][j] 存储索引位置为 i i i 的叶子,处于 j j j 状态下的最小调整次数。同时定义 isYellow、isRed 布尔类型变量判断第 i i i 位叶子是否为黄色、红色,如果是则值为1。

j = 0 表示状态1,j = 1 表示状态2,j = 2 表示状态 3

状态转移

现在我们开始梳理状态转移方程:

  • 情况一:如果当前叶子颜色最终处于状态一,当前叶子、该叶子的前一片叶子,一定是红色。同时:当前叶子如果不是红色就需要将黄色替换为红色(isYellow==true)。

d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] + i s Y e l l o w dp[i] [0]=dp[i-1] [0]+isYellow dp[i][0]=dp[i1][0]+isYellow

  • 情况二:如果当前叶子颜色最终处于状态二,当前这片一定是黄色,如果为红色则需要调整。但是前一片叶子可能是黄色或红色,也就是说可能处于状态一、状态而。为了调整次数的最小,选择这两种调整状态的最小修改次数调整该位状态:

d p [ i ] [ 1 ] = M a t h . m i n ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] ) + i s R e d dp[i][1] = Math.min(dp[i-1][0],dp[i-1][1])+isRed dp[i][1]=Math.min(dp[i1][0],dp[i1][1])+isRed

  • 情况三:如果当前状态为状态三,该位只能是红色,前一个状态为状态二或状态三,与状态二转移方程类似:

d p [ i ] [ 2 ] = M a t h . m i n ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 2 ] ) + i s Y e l l o w dp[i][2]=Math.min(dp[i-1][1],dp[i-1][2])+isYellow dp[i][2]=Math.min(dp[i1][1],dp[i1][2])+isYellow

返回结果

因为最后一片的状态一定是状态三,因此 d p [ n − 1 ] [ 2 ] dp[n-1][2] dp[n1][2] 一定是题目所求的值。

2、代码部分

class Solution {
    public int minimumOperations(String leaves) {
        int n=leaves.length();
        int [][]dp=new int[n][3];
        dp[0][0]=leaves.charAt(0)=='y'?1:0;
        int MAX=Integer.MAX_VALUE/2;
        dp[0][1]=MAX;
        dp[0][2]=MAX;
        for(int i=1;i<n;++i){
            char cur=leaves.charAt(i);
            int isYellow=cur=='y'?1:0;
            int isRed=cur=='r'?1:0;
            dp[i][0]=dp[i-1][0]+isYellow;
            dp[i][1]=Math.min(dp[i-1][0],dp[i-1][1])+isRed;
            dp[i][2]=Math.min(dp[i-1][1],dp[i-1][2])+isYellow;
        }
        return dp[n-1][2];
    }
}

批注:该写法可被优化为一维形式

写在最后

代码、论述中有任何问题,欢迎大家指出,同时如果有任何疑问,也能够在评论区中留言,大家共同讨论共同进步!

如果觉得博主写的不错的话,可以点赞支持一下!

你可能感兴趣的:(力扣精选题,算法,数据结构,leetcode)