91. 最小调整代价
一、 原题
描述
给一个整数数组,调整每个数的大小,使得相邻的两个数的差不大于一个给定的整数target,调整每个数的代价为调整前后的差的绝对值,求调整代价之和最小是多少。
你可以假设数组中每个整数都是正整数,且小于等于100。
样例
对于数组[1, 4, 2, 3]和target=1,最小的调整方案是调整为[2, 3, 2, 3],调整代价之和是2。返回2。
二、 求解
2.1 动态规划
思路:
构建一个n×101的dp二维数组, dp[i][j]表示 A[0~i] 中A[i]调整到 j 最小代价和, dp[i][j] 记录的是A中0 - i个元素中A[i] 调整到 j 时整体最小代价和;
- 由此可以推出: dp[i][j] = dp[i - 1][k] + Math.abs( A[i] - j ), 由于k是变化的,j - target <= k <= j + target, 由此取dp[i-1][k] 的最小值 --> dp[i][j] 最小值
- 初始化dp[0][j], 表示A[0] 调整到 j 时最小代价和, 由于只有一个数A[0], 因此dp[0][j] = Math.abs(A[0] - j)
- 从上到下, 从左到右, 计算出dp[i][j]的值, 取dp[A.szie() - 1][j] 中最小的值 即为 最小的调整代价和;
public class Solution {
/*
* @param A: An integer array
* @param target: An integer
* @return: An integer
*/
public int MinAdjustmentCost(List<Integer> A, int target) {
// write your code here
if(A == null) return -1;
int len = A.size();
int[][] dp = new int[len][101];
for(int i = 0; i <= 100; i++){
dp[0][i] = Math.abs(A.get(0) - i);
}
for(int i = 1; i < len; i ++){
for(int j = 0; j < 101; j++){
dp[i][j] = Integer.MAX_VALUE;
int diff = Math.abs(A.get(i) - j);
int start = (j - target < 0) ? 0 : j - target;
int end = (j + target > 100) ? 100 : j + target;
for(; start <= end; start++){
dp[i][j] = Math.min(dp[i-1][start] + diff, dp[i][j]);
}
}
}
int res = Integer.MAX_VALUE;
for(int i = 0; i < 101; i++){
res = Math.min(res, dp[len - 1][i]);
}
return res;
}
}