Problem#
You are given a 0-indexed integer array nums
. In one operation, you can:
Choose an index i
in the range 0 <= i < nums.length
Set nums[i]
to nums[i] + 1
or nums[i] - 1
Return _theminimum number of operations to make _nums
non-decreasing or non-increasing .
Examples#
Example 1:
1
2
3
4
5
6
7
8
9
10
Input: nums = [ 3 , 2 , 4 , 5 , 0 ]
Output: 4
Explanation:
One possible way to turn nums into non- increasing order is to:
- Add 1 to nums[ 1 ] once so that it becomes 3.
- Subtract 1 from nums[ 2 ] once so it becomes 3.
- Subtract 1 from nums[ 3 ] twice so it becomes 3.
After doing the 4 operations, nums becomes [ 3 , 3 , 3 , 3 , 0 ] which is in non- increasing order.
Note that it is also possible to turn nums into [ 4 , 4 , 4 , 4 , 0 ] in 4 operations.
It can be proven that 4 is the minimum number of operations needed.
Example 2:
1
2
3
Input: nums = [ 2 , 2 , 3 , 4 ]
Output: 0
Explanation: nums is already in non- decreasing order, so no operations are needed and we return 0.
Example 3:
1
2
3
Input: nums = [ 0 ]
Output: 0
Explanation: nums is already in non- decreasing order, so no operations are needed and we return 0.
Constraints:
1 <= nums.length <= 1000
0 <= nums[i] <= 1000
Follow up: Can you solve it in O(n*log(n))
time complexity?
Solution#
Method 1 – Dynamic Programming (DP) with Value Compression#
Intuition#
To minimize the number of operations to make the array non-decreasing or non-increasing, we can use DP. For each position, we try to set the value to any possible value and compute the minimum cost. Value compression helps reduce the DP state space.
Approach#
Collect all unique values in nums
and sort them for compression.
For non-decreasing:
Let dp[i][j]
be the minimum operations to make the first i+1
elements non-decreasing, with nums[i]
set to the j
-th value.
For each i
, for each possible value, try all previous values <=
current and update the cost.
For non-increasing:
Similar, but for each possible value, try all previous values >=
current.
The answer is the minimum of the two DP results.
Code#
Cpp
Go
Java
Kotlin
Python
Rust
Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public :
int minimumOperations(vector< int >& nums) {
vector< int > vals = nums;
sort(vals.begin(), vals.end());
vals.erase(unique(vals.begin(), vals.end()), vals.end());
int n = nums.size(), m = vals.size();
vector< vector< int >> dp1(n, vector< int > (m, 1e9 )), dp2(n, vector< int > (m, 1e9 ));
for (int j = 0 ; j < m; ++ j) dp1[0 ][j] = abs(nums[0 ] - vals[j]), dp2[0 ][j] = abs(nums[0 ] - vals[j]);
for (int i = 1 ; i < n; ++ i) {
int mn1 = 1e9 , mn2 = 1e9 ;
for (int j = 0 ; j < m; ++ j) {
mn1 = min(mn1, dp1[i- 1 ][j]);
dp1[i][j] = mn1 + abs(nums[i] - vals[j]);
}
for (int j = m- 1 ; j >= 0 ; -- j) {
mn2 = min(mn2, dp2[i- 1 ][j]);
dp2[i][j] = mn2 + abs(nums[i] - vals[j]);
}
}
int ans = 1e9 ;
for (int j = 0 ; j < m; ++ j) ans = min({ans, dp1[n- 1 ][j], dp2[n- 1 ][j]});
return ans;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
func minimumOperations (nums []int ) int {
vals := append([]int {}, nums ... )
sort .Ints (vals )
vals = unique (vals )
n , m := len(nums ), len(vals )
dp1 := make([][]int , n )
dp2 := make([][]int , n )
for i := range dp1 {
dp1 [i ] = make([]int , m )
dp2 [i ] = make([]int , m )
}
for j := 0 ; j < m ; j ++ {
dp1 [0 ][j ] = abs (nums [0 ]- vals [j ])
dp2 [0 ][j ] = abs (nums [0 ]- vals [j ])
}
for i := 1 ; i < n ; i ++ {
mn1 , mn2 := 1 << 30 , 1 << 30
for j := 0 ; j < m ; j ++ {
if dp1 [i - 1 ][j ] < mn1 {
mn1 = dp1 [i - 1 ][j ]
}
dp1 [i ][j ] = mn1 + abs (nums [i ]- vals [j ])
}
for j := m - 1 ; j >= 0 ; j -- {
if dp2 [i - 1 ][j ] < mn2 {
mn2 = dp2 [i - 1 ][j ]
}
dp2 [i ][j ] = mn2 + abs (nums [i ]- vals [j ])
}
}
ans := 1 << 30
for j := 0 ; j < m ; j ++ {
if dp1 [n - 1 ][j ] < ans {
ans = dp1 [n - 1 ][j ]
}
if dp2 [n - 1 ][j ] < ans {
ans = dp2 [n - 1 ][j ]
}
}
return ans
}
func abs (x int ) int { if x < 0 { return - x }; return x }
func unique (a []int ) []int {
if len(a ) == 0 { return a }
res := []int {a [0 ]}
for i := 1 ; i < len(a ); i ++ {
if a [i ] != a [i - 1 ] {
res = append(res , a [i ])
}
}
return res
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.*;
class Solution {
public int minimumOperations (int [] nums) {
int [] vals = Arrays.copyOf (nums, nums.length );
Arrays.sort (vals);
int m = 1;
for (int i = 1; i < vals.length ; i++ ) if (vals[ i] != vals[ i- 1] ) vals[ m++] = vals[ i] ;
int n = nums.length ;
int [][] dp1 = new int [ n][ m] , dp2 = new int [ n][ m] ;
for (int j = 0; j < m; ++ j) dp1[ 0][ j] = Math.abs (nums[ 0]- vals[ j] );
for (int j = 0; j < m; ++ j) dp2[ 0][ j] = Math.abs (nums[ 0]- vals[ j] );
for (int i = 1; i < n; ++ i) {
int mn1 = Integer.MAX_VALUE , mn2 = Integer.MAX_VALUE ;
for (int j = 0; j < m; ++ j) {
mn1 = Math.min (mn1, dp1[ i- 1][ j] );
dp1[ i][ j] = mn1 + Math.abs (nums[ i]- vals[ j] );
}
for (int j = m- 1; j >= 0; -- j) {
mn2 = Math.min (mn2, dp2[ i- 1][ j] );
dp2[ i][ j] = mn2 + Math.abs (nums[ i]- vals[ j] );
}
}
int ans = Integer.MAX_VALUE ;
for (int j = 0; j < m; ++ j) ans = Math.min (ans, Math.min (dp1[ n- 1][ j] , dp2[ n- 1][ j] ));
return ans;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
fun minimumOperations (nums: IntArray): Int {
val vals = nums.sorted().distinct()
val n = nums.size
val m = vals.size
val dp1 = Array(n) { IntArray(m) }
val dp2 = Array(n) { IntArray(m) }
for (j in 0 until m) {
dp1[0 ][j] = kotlin.math.abs(nums[0 ] - vals[j])
dp2[0 ][j] = kotlin.math.abs(nums[0 ] - vals[j])
}
for (i in 1 until n) {
var mn1 = Int .MAX_VALUE
var mn2 = Int .MAX_VALUE
for (j in 0 until m) {
mn1 = minOf(mn1, dp1[i-1 ][j])
dp1[i][j] = mn1 + kotlin.math.abs(nums[i] - vals[j])
}
for (j in m-1 downTo 0 ) {
mn2 = minOf(mn2, dp2[i-1 ][j])
dp2[i][j] = mn2 + kotlin.math.abs(nums[i] - vals[j])
}
}
var ans = Int .MAX_VALUE
for (j in 0 until m) ans = minOf(ans, dp1[n-1 ][j], dp2[n-1 ][j])
return ans
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution :
def minimumOperations (self, nums: list[int]) -> int:
vals = sorted(set(nums))
n, m = len(nums), len(vals)
dp1 = [ [0 ]* m for _ in range(n) ]
dp2 = [ [0 ]* m for _ in range(n) ]
for j in range(m):
dp1[0 ][j] = abs(nums[0 ] - vals[j])
dp2[0 ][j] = abs(nums[0 ] - vals[j])
for i in range(1 , n):
mn1 = mn2 = float('inf' )
for j in range(m):
mn1 = min(mn1, dp1[i- 1 ][j])
dp1[i][j] = mn1 + abs(nums[i] - vals[j])
for j in range(m- 1 , - 1 , - 1 ):
mn2 = min(mn2, dp2[i- 1 ][j])
dp2[i][j] = mn2 + abs(nums[i] - vals[j])
ans = float('inf' )
for j in range(m):
ans = min(ans, dp1[n- 1 ][j], dp2[n- 1 ][j])
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
impl Solution {
pub fn minimum_operations (nums: Vec< i32 > ) -> i32 {
let mut vals = nums.clone();
vals.sort();
vals.dedup();
let n = nums.len();
let m = vals.len();
let mut dp1 = vec! [vec! [1_000_000_000 ; m]; n];
let mut dp2 = vec! [vec! [1_000_000_000 ; m]; n];
for j in 0 .. m {
dp1[0 ][j] = (nums[0 ] - vals[j]).abs();
dp2[0 ][j] = (nums[0 ] - vals[j]).abs();
}
for i in 1 .. n {
let mut mn1 = 1_000_000_000 ;
let mut mn2 = 1_000_000_000 ;
for j in 0 .. m {
mn1 = mn1.min(dp1[i- 1 ][j]);
dp1[i][j] = mn1 + (nums[i] - vals[j]).abs();
}
for j in (0 .. m).rev() {
mn2 = mn2.min(dp2[i- 1 ][j]);
dp2[i][j] = mn2 + (nums[i] - vals[j]).abs();
}
}
let mut ans = 1_000_000_000 ;
for j in 0 .. m {
ans = ans.min(dp1[n- 1 ][j].min(dp2[n- 1 ][j]));
}
ans
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
minimumOperations (nums : number []): number {
const vals = Array.from (new Set (nums )).sort ((a , b ) => a - b );
const n = nums .length , m = vals .length ;
const dp1 = Array.from ({length : n }, () => Array(m ).fill (0 ));
const dp2 = Array.from ({length : n }, () => Array(m ).fill (0 ));
for (let j = 0 ; j < m ; ++ j ) {
dp1 [0 ][j ] = Math.abs (nums [0 ] - vals [j ]);
dp2 [0 ][j ] = Math.abs (nums [0 ] - vals [j ]);
}
for (let i = 1 ; i < n ; ++ i ) {
let mn1 = Infinity , mn2 = Infinity ;
for (let j = 0 ; j < m ; ++ j ) {
mn1 = Math.min (mn1 , dp1 [i - 1 ][j ]);
dp1 [i ][j ] = mn1 + Math.abs (nums [i ] - vals [j ]);
}
for (let j = m - 1 ; j >= 0 ; -- j ) {
mn2 = Math.min (mn2 , dp2 [i - 1 ][j ]);
dp2 [i ][j ] = mn2 + Math.abs (nums [i ] - vals [j ]);
}
}
let ans = Infinity ;
for (let j = 0 ; j < m ; ++ j ) ans = Math.min (ans , dp1 [n - 1 ][j ], dp2 [n - 1 ][j ]);
return ans ;
}
}
Complexity#
⏰ Time complexity: O(nk)
, where n is the length of nums and k is the number of unique values in nums.
🧺 Space complexity: O(nk)
, for the DP tables.