Leetcode - 256&265. 粉刷房子

代码未经过验证,但解题思路是正确的:
class Solution {

    /**
     * 已知条件1:数组[r, b, g]表示将某个房子粉刷成红/蓝/绿色时所需的价格
     * 已知条件2:有一排房子,共n个,其粉刷价格用一个(n * 3)的矩阵来表示,相邻房子不能粉刷成相同颜色
     * 题目要求:现对这些房子进行粉刷,问最小的花费是多少
     */

    public int minCost(int[][] costs) {
        if(costs == null || costs.length == 0)
            return 0;

        //使用动态规划:假设第0到第(i - 1)个房子都已经被粉刷好了,现要粉刷第i个房子
        
        //不妨假设将第i个房子粉刷成红色,该房子的花费为costs[i][0]
        //此时,需要看将第(i - 1)个房子粉刷成蓝色或绿色时前(i - 1)个房子的总花费,取其较小值preMinBG
        //那么,将第0到第i个房子粉刷好,并且第i个房子为红色的最小花费是(costs[i][0] + preMinBG)
        
        //将第i个房子刷成蓝/绿色时,前i个房子的最小花费是也可以用类似的方法求得

        for(int i = 1; i < costs.length; i++){
            int[] thisHouse = costs[i], preHouse = costs[i - 1];
            thisHouse[0] += Math.min(preHouse[1], preHouse[2]);
            thisHouse[1] += Math.min(preHouse[0], preHouse[2]);
            thisHouse[2] += Math.min(preHouse[0], preHouse[1]);
        }

        //返回最后一个数组中的最小元素即可
        int[] lastHouse = costs[costs.length - 1];
        return Math.min(Math.min(lastHouse[0], lastHouse[1]), lastHouse[2]);
    }


    /**
     * 进阶(题目二):现在颜色不止红蓝绿三种,而是有k种颜色可选,问粉刷n个房子的最小花费;要求时间复杂度O(nk)
     */
    
    public int minCostII(int[][] costs) {
        if(costs == null || costs.length == 0)
            return 0;

        //使用动态规划:假设第0到第(i - 1)个房子都已经被粉刷好了,现要粉刷第i个房子
        //不妨第(i - 1)个房子粉刷成红色时花费最少,为preRedCost;而粉刷成蓝色是花费第二少,为preBlueCost
        //1. 如果第i个房子粉刷成红色,花费为r,则此时将前i个房子粉刷好的最小花费是(r + preBlueCost)
        //2. 如果第i个房子粉刷成非红色,花费为a,则此时将前i个房子粉刷好的最小花费是(a + preRedCost)

        //只需要维护前(i - 1)个房子的最小花费和第二小花费,以及最小花费时第(i - 1)个房子的颜色即可
        int preMinCost = 0, preMinCostIdx = -1, preSecondMinCost = 0;

        for(int[] cur: costs){
            int curMinCost = Integer.MAX_VALUE, curMinCostIdx = -1, curSecondMinCost = Integer.MAX_VALUE;
            
            for(int j = 0; j < cur.length; j++){
                
                //计算出当前房子粉刷成第j种颜色时的花费
                cur[j] += j == preMinCostIdx ? preSecondMinCost : preMinCost;
                
                //更新当前房子的最小花费等数据
                if(cur[j] < curMinCost){
                    curSecondMinCost = curMinCost;
                    curMinCost = cur[j];
                    curMinCostIdx = j;
                } else if(cur[j] < curSecondMinCost){
                    curSecondMinCost = cur[j];
                }
            }
            
            //为下次循环做准备
            preMinCost = curMinCost;
            preMinCostIdx = curMinCostIdx;
            preSecondMinCost = curSecondMinCost;
        }
        
        return preMinCost;
    }
}
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务