タイトルアドレス:
https://www.lintcode.com/problem/minimum-adjustment-cost/description
整数の配列を指定すると、変更前と変更後の数値間の差の絶対値を犠牲にして、内部の数値を変更できます。数値ターゲットが与えられた場合、配列内の2つの隣接する数値間の差の絶対値がターゲット以下になるように最小コストが必要であり、最小コストは何であるかです。
動的プログラミングで解決できます。セット は、 に調整します の場合、隣接する数値間の差に到達するために必要な最小コストは目標を超えません。次にあります は は2つの部分に分割できます。最初の部分は に調整します 必要な費用、2番目の部分は上記の前提の下で、調整前 の数、および調整前に必要な最小コスト の数にも制限があります。つまり、 調整範囲は、隣接する数値の差が目標を下回るという制限を満たしている必要があり、この制限を満たしていれば、最小コストを選択できます。タイトルは言う 数が正の数ではありません以上 、調整はこの範囲に制限できます。さらに、最適な解の数が比率に調整されないことを証明できます 依然として大きい数値です。そうでない場合は、最大値よりも大きい数値を最大値に調整できるため、総コストが明らかに削減され、配列の隣接する数値間の差も小さくなります。 、どちらが明らかに優れています。この方法で最適化できます の範囲。コードは次のとおりです。
import java.util.Arrays;
import java.util.List;
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 || A.size() == 0) {
return 0;
}
// 寻找A的最大值
int max = Integer.MIN_VALUE;
for (int num : A) {
max = Math.max(max, num);
}
int[][] dp = new int[A.size()][max + 1];
// 先初始化为最大值,然后不停更新
for (int[] arr : dp) {
Arrays.fill(arr, Integer.MAX_VALUE);
}
// 枚举第0个数要调整为谁
for (int i = 1; i <= max; i++) {
dp[0][i] = Math.abs(A.get(0) - i);
}
// 开始枚举第i个数要调整为j会得到什么解
for (int i = 1; i < A.size(); i++) {
for (int j = 1; j <= max; j++) {
// 计算A[i - 1]可以调整到的数的范围
int l = Math.max(j - target, 1), r = Math.min(j + target, max);
for (int k = l; k <= r; k++) {
dp[i][j] = Math.min(dp[i][j], dp[i - 1][k] + Math.abs(A.get(i) - j));
}
}
}
// 最终答案其实就是调整最后一个数到i的情况下的所有最小花费的最小值
int res = Integer.MAX_VALUE;
for (int i = 1; i <= max; i++) {
res = Math.min(res, dp[A.size() - 1][i]);
}
return res;
}
}
時間の複雑さ 、スペース 、 は の最大数