剑指 Offer II 091. 粉刷房子(256. 粉刷房子)

题目:

 

思路:

【1】动态规划的方式,首先对于动态规划的问题是分成子问题,那么子问题又可以当做是一个小汇总,如

对于 1≤i<n,第 i 号房子和第 i−1 号房子的颜色必须不同,
因此当第 i 号房子被粉刷成某一种颜色时,第 i−1 号房子只能被粉刷成另外两种颜色之一。
当第 i 号房子分别被粉刷成三种颜色时,粉刷第 0 号房子到第 i 号房子的最小花费成本计算如下:
dp[i][0]=min⁡(dp[i−1][1],dp[i−1][2])+costs[i][0]
dp[i][1]=min⁡(dp[i−1][0],dp[i−1][2])+costs[i][1]
dp[i][2]=min⁡(dp[i−1][0],dp[i−1][1])+costs[i][2] 

三种颜色的情况可以合并为一个状态转移方程,对于 1≤i<n 和 0≤j<3,状态转移方程如下:
dp[i][j]=min⁡(dp[i−1][(j+1) mod 3],dp[i−1][(j+2) mod 3])+costs[i][j] 

计算结束时,dp[n−1] 中的最小值即为粉刷所有房子的最小花费成本。

 

 

 

代码展示:

动态规划的方式:

//时间2 ms击败16.60%
//内存40.9 MB击败60.2%
//时间复杂度:O(n),其中 n 是房子个数。
//需要遍历全部房子一次,由于颜色数量固定是三种,因此对于每个房子计算粉刷房子的最小花费成本的时间是 O(1),总时间复杂度是 O(n)。
//空间复杂度:O(1)。使用空间优化的方法,只需要维护一个长度为 3 的数组,空间复杂度是 O(1)。
class Solution {
    public int minCost(int[][] costs) {
        int n = costs.length;
        int[] dp = new int[3];
        for (int j = 0; j < 3; j++) {
            dp[j] = costs[0][j];
        }
        for (int i = 1; i < n; i++) {
            int[] dpNew = new int[3];
            for (int j = 0; j < 3; j++) {
                dpNew[j] = Math.min(dp[(j + 1) % 3], dp[(j + 2) % 3]) + costs[i][j];
            }
            dp = dpNew;
        }
        return Arrays.stream(dp).min().getAsInt();
    }
}

//在原本的数组上进行统计
//时间1 ms击败84.11%
//内存40.8 MB击败64.27%
class Solution {
    public int minCost(int[][] costs) {
        int n=costs.length;
        for(int i=1;i<n;i++){
            costs[i][0]+=Math.min(costs[i-1][2],costs[i-1][1]);
            costs[i][1]+=Math.min(costs[i-1][2],costs[i-1][0]);
            costs[i][2]+=Math.min(costs[i-1][0],costs[i-1][1]);
        }
        return Math.min(costs[n-1][0],Math.min(costs[n-1][1],costs[n-1][2]));
    }
}

 

posted @ 2023-04-03 11:28  忧愁的chafry  阅读(14)  评论(0编辑  收藏  举报