Given an integer array A and an integer target, adjust each integer so that the absolute difference between every pair of adjacent integers is not greater than target. Let B be the adjusted array. Minimize the total adjustment cost defined as the sum of |A[i] - B[i]| over all indices i.
At index i, if we decide to set B[i] = v, then for the next index i+1 we may only choose values v' such that |v' - v| <= target.
A naive recursive solution tries all valid adjusted values for each position and keeps the minimum accumulated cost. This explores the full search tree without caching, leading to exponential time.
Let solve(i, prev) be the minimum additional cost to adjust positions i..n-1 given that the previous adjusted value is prev (for i > 0). For i = 0, there is no previous value constraint, so we simply try all values v in [1..100] as starting points.
If i == n, return 0 (no cost beyond end).
Determine candidate range for v:
If i == 0: v from 1..100.
Else: v from max(1, prev - target) to min(100, prev + target).
For each v in the range, cost = abs(A[i] - v) + solve(i+1, v); take the minimum.
Return that minimum.
Edge cases:
Empty array → cost 0.
Single element → min_{v in 1..100} |A[0] - v| (achieved at v = A[0]).
#include<vector>#include<cmath>#include<limits>usingnamespace std;
classSolution {
constint MAXV =100;
int n, target;
const vector<int>* arr;
intdfs(int i, int prev) {
if (i == n) return0;
int lo =1, hi = MAXV;
if (i >0) {
lo = max(1, prev - target);
hi = min(MAXV, prev + target);
}
int best = numeric_limits<int>::max();
for (int v = lo; v <= hi; ++v) {
int cost = abs((*arr)[i] - v) + dfs(i +1, v);
if (cost < best) best = cost;
}
return best;
}
public:int minAdjustmentCost(const vector<int>& A, int tgt) {
arr =&A; target = tgt; n = (int)A.size();
if (n ==0) return0;
returndfs(0, 0);
}
};
import java.util.*;
classSolution {
privateint n, target;
private List<Integer> A;
privateintdfs(int i, int prev) {
if (i == n) return 0;
int lo = 1, hi = 100;
if (i > 0) {
lo = Math.max(1, prev - target);
hi = Math.min(100, prev + target);
}
int best = Integer.MAX_VALUE;
for (int v = lo; v <= hi; v++) {
int cost = Math.abs(A.get(i) - v) + dfs(i + 1, v);
best = Math.min(best, cost);
}
return best;
}
publicintminAdjustmentCost(ArrayList<Integer> arr, int tgt) {
A = arr; target = tgt; n = A.size();
if (n == 0) return 0;
return dfs(0, 0);
}
}
from typing import List
classSolution:
defminAdjustmentCost(self, A: List[int], target: int) -> int:
n = len(A)
if n ==0:
return0 MAXV =100from math import inf
defdfs(i: int, prev: int) -> int:
if i == n:
return0if i ==0:
lo, hi =1, MAXV
else:
lo = max(1, prev - target)
hi = min(MAXV, prev + target)
best = inf
for v in range(lo, hi +1):
best = min(best, abs(A[i] - v) + dfs(i +1, v))
return best
return dfs(0, 0)
The pure recursion repeats subproblems: the minimum cost for suffix i given previous adjusted value prev appears many times.
Cache (i, prev) results to avoid recomputation. This reduces exponential growth to polynomial O(n * V * T) where V=100 and T bounds the neighbor range (2*target+1).
Use a 2D memo table memo[i][prev] initialized to -1 meaning unknown (treat prev in 0..100; we use prev=0 only for the first position as a sentinel meaning “no previous”).
Recurrence identical to Method 1, but before computing we check cache.
#include<vector>#include<algorithm>#include<limits>usingnamespace std;
classSolution {
constint MAXV =100;
int n, target; const vector<int>* A;
vector<vector<int>> memo; // memo[i][prev]
intdfs(int i, int prev) {
if (i == n) return0;
if (memo[i][prev] !=-1) return memo[i][prev];
int lo =1, hi = MAXV;
if (i >0) { lo = max(1, prev - target); hi = min(MAXV, prev + target); }
int best = numeric_limits<int>::max();
for (int v = lo; v <= hi; ++v) {
int cost = abs((*A)[i] - v) + dfs(i +1, v);
if (cost < best) best = cost;
}
return memo[i][prev] = best;
}
public:int minAdjustmentCost(const vector<int>& arr, int tgt) {
A =&arr; target = tgt; n = (int)arr.size();
if (n ==0) return0;
memo.assign(n, vector<int>(MAXV +1, -1));
returndfs(0, 0);
}
};
import java.util.*;
classSolution {
privateint n, target; private List<Integer> A;
privateint[][] memo; // memo[i][prev]privateintdfs(int i, int prev) {
if (i == n) return 0;
if (memo[i][prev]!=-1) return memo[i][prev];
int lo = 1, hi = 100;
if (i > 0) { lo = Math.max(1, prev - target); hi = Math.min(100, prev + target); }
int best = Integer.MAX_VALUE;
for (int v = lo; v <= hi; v++) {
int cost = Math.abs(A.get(i) - v) + dfs(i + 1, v);
best = Math.min(best, cost);
}
return memo[i][prev]= best;
}
publicintminAdjustmentCost(ArrayList<Integer> arr, int tgt) {
A = arr; target = tgt; n = A.size();
if (n == 0) return 0;
memo =newint[n][101];
for (int i = 0; i < n; i++) Arrays.fill(memo[i], -1);
return dfs(0, 0);
}
}
from typing import List
from functools import lru_cache
classSolution:
defminAdjustmentCost(self, A: List[int], target: int) -> int:
n = len(A)
if n ==0:
return0 MAXV =100@lru_cache(None)
defdfs(i: int, prev: int) -> int:
if i == n:
return0if i ==0:
lo, hi =1, MAXV
else:
lo = max(1, prev - target)
hi = min(MAXV, prev + target)
best =10**12for v in range(lo, hi +1):
best = min(best, abs(A[i] - v) + dfs(i +1, v))
return best
return dfs(0, 0)
⏰ Time complexity: O(n * V * T) — at most n * (V+1) states and each iterates up to 2*target+1 values (bounded by V). With V=100, effectively O(n * target).
🧺 Space complexity: O(n * V) for memo table (or recursion cache) plus O(n) stack depth.
For each position i and a possible adjusted value v (1..100), consider the minimum cost to make A[0..i] valid with B[i] = v.
Let dp[i][v] be this minimum cost. To compute it we look at all possible previous adjusted values pv such that |v - pv| <= target and take dp[i-1][pv] + |A[i] - v|.
#include<vector>#include<algorithm>#include<limits>usingnamespace std;
classSolution {
public:int minAdjustmentCost(const vector<int>& A, int target) {
int n = A.size();
if (n ==0) return0;
constint MAXV =100;
constint INF = numeric_limits<int>::max() /4;
vector<vector<int>> dp(n, vector<int>(MAXV +1, INF));
for (int v =1; v <= MAXV; ++v) dp[0][v] = abs(A[0] - v);
for (int i =1; i < n; ++i) {
for (int v =1; v <= MAXV; ++v) {
for (int pv = max(1, v - target); pv <= min(MAXV, v + target); ++pv) {
dp[i][v] = min(dp[i][v], dp[i-1][pv] + abs(A[i] - v));
}
}
}
int ans = INF;
for (int v =1; v <= MAXV; ++v) ans = min(ans, dp[n-1][v]);
return ans;
}
};
import java.util.*;
classSolution {
publicintminAdjustmentCost(ArrayList<Integer> A, int target) {
if (A ==null|| A.size() == 0) return 0;
finalint MAXV = 100;
finalint INF = Integer.MAX_VALUE/ 4;
int n = A.size();
int[][] dp =newint[n][MAXV + 1];
for (int i = 0; i < n; i++) Arrays.fill(dp[i], INF);
for (int v = 1; v <= MAXV; v++) dp[0][v]= Math.abs(A.get(0) - v);
for (int i = 1; i < n; i++) {
for (int v = 1; v <= MAXV; v++) {
for (int pv = Math.max(1, v - target); pv <= Math.min(MAXV, v + target); pv++) {
dp[i][v]= Math.min(dp[i][v], dp[i-1][pv]+ Math.abs(A.get(i) - v));
}
}
}
int ans = INF;
for (int v = 1; v <= MAXV; v++) ans = Math.min(ans, dp[n-1][v]);
return ans;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from typing import List
classSolution:
defminAdjustmentCost(self, A: List[int], target: int) -> int:
n = len(A)
if n ==0:
return0 MAXV =100 INF =10**9 dp = [[INF] * (MAXV +1) for _ in range(n)]
for v in range(1, MAXV +1):
dp[0][v] = abs(A[0] - v)
for i in range(1, n):
for v in range(1, MAXV +1):
for pv in range(max(1, v - target), min(MAXV, v + target) +1):
dp[i][v] = min(dp[i][v], dp[i-1][pv] + abs(A[i] - v))
return min(dp[n-1][1:])
⏰ Time complexity: O(n * V * T) where n = len(A), V = 100 is the bounded value range, and T = target (more precisely the inner loop iterates up to 2*target+1 values). So worst-case O(n * V * T) which is effectively O(n * target) with constant V=100.
🧺 Space complexity: O(n * V) for the 2D dp table. (Can be optimized to O(V) — see Method 2.)
Method 4 - Dynamic Programming (Space-optimized, rolling array)#
from typing import List
classSolution:
defminAdjustmentCost(self, A: List[int], target: int) -> int:
n = len(A)
if n ==0:
return0 MAXV =100 INF =10**9 prev = [INF] * (MAXV +1)
cur = [INF] * (MAXV +1)
for v in range(1, MAXV +1):
prev[v] = abs(A[0] - v)
for i in range(1, n):
for v in range(1, MAXV +1):
cur[v] = INF
for v in range(1, MAXV +1):
for pv in range(max(1, v - target), min(MAXV, v + target) +1):
cur[v] = min(cur[v], prev[pv] + abs(A[i] - v))
prev, cur = cur, prev
return min(prev[1:])
⏰ Time complexity: O(n * V * T) where n = len(A), V = 100 (bounded value range), and T ≈ target (inner scan over 2*target+1 values). With V constant this is effectively O(n * target).
🧺 Space complexity: O(V) for the space-optimized version (Method 2) and O(n * V) for the full 2D DP (Method 1).