lintcode 516. 房屋染色 II
阿新 • • 發佈:2018-12-30
描述
這裡有n
個房子在一列直線上,現在我們需要給房屋染色,共有k
種顏色。每個房屋染不同的顏色費用也不同,你需要設計一種染色方案使得相鄰的房屋顏色不同,並且費用最小。
費用通過一個n
xk
的矩陣給出,比如cost[0][0]
表示房屋0
染顏色0
的費用,cost[1][2]
表示房屋1
染顏色2
的費用。
所有費用都是正整數
樣例
costs
= [[14,2,11],[11,14,5],[14,3,10]]
return 10
房屋 0
顏色 1
, 房屋 1
顏色 2
, 房屋 2
1
, 2 + 5 + 3 = 10
挑戰
用O(nk)的時間複雜度解決。
因為想到染到最後一個房子的最小值,為染到前一個房子的不同顏色最小值 與最後一個房子的cost得出。所以想到dp。dp[i][j]代表結束在編號i,顏色k的最小值。求dp[i][j]是可以遍歷i-1房子的不同顏色,所以容易想到O(nk^2)解法。但觀察到染到i的不同顏色最小值只是基於,i-1的最小值 和 i-1的第二小值。所以只限用fi,si兩個下標分別記錄染到房子i-1時最小顏色,和第二小顏色就行了,時間複雜度O(nk)。
O(nk^2)solution。
public int minCostII(int[][] costs) { if(costs==null||costs.length==0) return 0; int n=costs.length,k=costs[0].length; int[][] dp=new int[n][k]; for(int j=0;j<k;j++){ dp[0][j]=costs[0][j]; } for(int i=1;i<n;i++){ for(int j=0;j<k;j++){ dp[i][j]=Integer.MAX_VALUE; for(int c=0;c<k;c++){ if(c==j) continue; dp[i][j]=Math.min(dp[i-1][c]+costs[i][j],dp[i][j]); } } } int min=dp[n-1][0]; for(int j=1;j<k;j++) min=Math.min(min,dp[n-1][j]); return min; }
O(nk) solution
public int minCostII(int[][] costs) {
if(costs==null||costs.length==0) return 0;
int n=costs.length,k=costs[0].length;
int[][] dp=new int[n][k];
int fi=-1,si=-1;
for(int j=0;j<k;j++){
dp[0][j]=costs[0][j];
if(fi==-1){
fi=j;
}else if(dp[0][j]<=dp[0][fi]){
si=fi;
fi=j;
}else if(si==-1||dp[0][j]<dp[0][si]){
si=j;
}
}
for(int i=1;i<n;i++){
//fi,si前一個下標,f,s當前下標
int f=-1,s=-1;
for(int j=0;j<k;j++){
if(dp[i-1][fi]==dp[i-1][si]||j!=fi){
dp[i][j]=dp[i-1][fi]+costs[i][j];
}else{
dp[i][j]=dp[i-1][si]+costs[i][j];
}
if(f==-1){
f=j;
}else if(dp[i][j]<=dp[i][f]){
s=f;
f=j;
}else if(s==-1||dp[i][j]<dp[i][s]){
s=j;
}
}
fi=f;
si=s;
}
return dp[n-1][fi];