Given an integer array, adjust each integers so that the difference of every adjacent integers are not greater than a given number target.
If the array before adjustment is A, the array after adjustment is B, you should minimize the sum of|A[i]-B[i]|
Notice
You can assume each number in the array is a positive integer and not greater than 100
.
Given [1,4,2,3]
and
target = 1
, one of the solutions is [2,3,2,3]
,
the adjustment cost is 2
and it's minimal.
Return 2
.
轉自http://www.cnblogs.com/yuzhangcmu/p/4153927.html
這道題真的慚愧,確實沒有想出來
可以用遞歸和動態規劃來解決這道題
遞歸,有點像word ladder和數獨一樣代碼如下
/**
* @param A: An integer array.
* @param target: An integer.
*/
public static int MinAdjustmentCost1(ArrayList<Integer> A, int target) {
// write your code here
if (A == null) {
return 0;
}
return rec(A, new ArrayList<Integer>(A), target, 0);
}
/*
* SOL 1:
* 最普通的遞歸方法。
* */
public static int rec(ArrayList<Integer> A, ArrayList<Integer> B, int target, int index) {
int len = A.size();
if (index >= len) {
// The index is out of range.
return 0;
}
int dif = 0;
int min = Integer.MAX_VALUE;
// If this is the first element, it can be from 1 to 100;
for (int i = 0; i <= 100; i++) {
if (index != 0 && Math.abs(i - B.get(index - 1)) > target) {
continue;
}
B.set(index, i);
dif = Math.abs(i - A.get(index));
dif += rec(A, B, target, index + 1);
min = Math.min(min, dif);
// 回溯
B.set(index, A.get(index));
}
return min;
}
更好的解法用動態規劃,dp[i][[j] i表示現在loop到的位置,j表示1-100的數字,dp[i][j]表示,當loop到i位置時,取j值時整個修改的最小值
所以最終的結果要 比較 dp[A.size()-1][1--100]的大小來決定整個變換的最小值, 這個有點像刷顏色的問題
/*
* SOLUTION 4:
* DP
* */
/**
* @param A: An integer array.
* @param target: An integer.
*/
public static int MinAdjustmentCost(ArrayList<Integer> A, int target) {
// write your code here
if (A == null || A.size() == 0) {
return 0;
}
// D[i][v]: 把index = i的值修改爲v,所需要的最小花費
int[][] D = new int[A.size()][101];
int size = A.size();
for (int i = 0; i < size; i++) {
for (int j = 1; j <= 100; j++) {
D[i][j] = Integer.MAX_VALUE;
if (i == 0) {
// The first element.
D[i][j] = Math.abs(j - A.get(i));
} else {
for (int k = 1; k <= 100; k++) {
// 不符合條件
if (Math.abs(j - k) > target) {
continue;
}
int dif = Math.abs(j - A.get(i)) + D[i - 1][k];
D[i][j] = Math.min(D[i][j], dif);
}
}
}
}
int ret = Integer.MAX_VALUE;
for (int i = 1; i <= 100; i++) {
ret = Math.min(ret, D[size - 1][i]);
}
return ret;
}
刷牆的問題:對比起來真是一模一樣
class Solution {
public:
/**
* @param costs n x 3 cost matrix
* @return an integer, the minimum cost to paint all houses
*/
int minCost(vector<vector<int>>& costs) {
// Write your code here
if (costs.size() == 0) //檢查邊界條件非常重要
return 0;
int n = costs.size();
vector<vector<int>> dp(n, vector<int>(3));
//dp[i][j] 表示計算到第i戶時,他選擇第j種顏色圖牆時的最小价錢
for (int i=0; i<3; i++)
{
dp[0][i] = costs[0][i];
}
for (int i=1; i<n; i++)
{
for (int j=0; j<3; j++)
{
int minC = INT_MAX;
for (int k=0; k<3; k++)
{
if (k != j)
{
minC = min(minC, dp[i-1][k]);
}
dp[i][j] = minC + costs[i][j];
}
}
}
int minRet = INT_MAX;
for (int i=0; i<3; i++)
{
minRet = min(minRet, dp[n-1][i]);
}
return minRet;
}
};