{x}
blog image

Make Array Non-decreasing or Non-increasing

Solution Explanation

This problem asks for the minimum number of operations to make an array either non-decreasing or non-increasing. The solution uses dynamic programming to efficiently find this minimum.

Core Idea:

The solution cleverly tackles the problem by solving two subproblems:

  1. Non-decreasing: Find the minimum operations needed to make the array non-decreasing.
  2. Non-increasing: Find the minimum operations needed to make the array non-increasing.

The final answer is the minimum of these two subproblem solutions.

Dynamic Programming Approach (for Non-decreasing):

The dynamic programming solution constructs a 2D array f where f[i][j] represents the minimum number of operations needed to make the first i elements of the array non-decreasing, ending with the value j.

  • Initialization: f[0][j] = 0 for all j (no operations needed for an empty array).
  • Recurrence Relation: For each i, f[i][j] is calculated as the minimum of f[i-1][k] + abs(nums[i-1] - j) for all k from 0 to 1000. This represents trying all possible values k for the previous element and adding the cost of changing nums[i-1] to j. abs(nums[i-1]-j) is the number of operations needed to change nums[i-1] to j.
  • Optimization: A running minimum is maintained during the inner loop to avoid unnecessary computations.

Code Breakdown (Python3 as an example):

def convertArray(self, nums: List[int]) -> int:
    def solve(nums):  # Function to solve for non-decreasing
        n = len(nums)
        f = [[0] * 1001 for _ in range(n + 1)] # DP table
        for i, x in enumerate(nums, 1):
            mi = inf  # Minimum operations so far
            for j in range(1001):  # Iterate through possible values
                if mi > f[i - 1][j]:  #Optimization
                    mi = f[i - 1][j]
                f[i][j] = mi + abs(x - j) #DP transition
        return min(f[n]) # minimum cost across all ending values
 
    return min(solve(nums), solve(nums[::-1])) #Solve for both decreasing and increasing and return min

The solve function implements the DP approach. The main function calls solve twice: once for the original array (non-decreasing) and once for the reversed array (non-increasing). The minimum of the two results is returned.

Time and Space Complexity:

  • Time Complexity: O(n * m), where n is the length of the array and m is the range of values (1001 in this case). The nested loops dominate the runtime.
  • Space Complexity: O(n * m) to store the DP table.

Other Languages:

The Java, C++, and Go solutions implement the same core algorithm but adapt the syntax and data structures to each language. The essential DP logic remains the same across all implementations.

Note: While the problem statement suggests a solution with O(n log n) time complexity, the provided DP solution has O(n*m) complexity where m is the range of values in the array. An O(n log n) solution may exist using advanced data structures or algorithms, but this DP solution is reasonably efficient for the given constraints.