写在前面
大家好我是秋刀鱼,今天刷力扣时做了一道LCP的题目。有刷过LCP的小伙伴一定知道LCP题目向来都是不当人的难,中等难度基本上就碾压LeetCode中大部分困难题目。这道题解题思路非常巧妙,给大家分享一下。
题目传送门
题目要求的是将收集到的红叶、黄叶按照 【红、黄、红】的顺序整理为三个部分,每个部分至少有一片叶子。同时能够调整任意一片叶子的颜色。
不难得知,整理为下面的状态时,叶子的排列顺序符合题意:
整理完毕后叶子的颜色排列一定是 红色、黄色、红色,不妨我们定义每片叶子所处的状态:
现在每一片都有了自己的状态,同时每一片最终处于的状态都有可能是这三种状态之一。
但是为了满足题意,每一个颜色块的数量至少为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[i−1][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[i−1][0],dp[i−1][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[i−1][1],dp[i−1][2])+isYellow
返回结果
因为最后一片的状态一定是状态三,因此 d p [ n − 1 ] [ 2 ] dp[n-1][2] dp[n−1][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];
}
}
批注:该写法可被优化为一维形式
写在最后
代码、论述中有任何问题,欢迎大家指出,同时如果有任何疑问,也能够在评论区中留言,大家共同讨论共同进步!
如果觉得博主写的不错的话,可以点赞支持一下!