Minimum Replacements to Sort the Array

Updated on 19 June, 2025
Minimum Replacements to Sort the Array header image

Problem Statement

Given a zero-indexed integer array nums, this problem involves a specialized operation whereby any element in the array can be replaced by any two elements whose sum is equal to the original element. The challenge is to determine the minimum number of such operations needed to transform the array into one that is sorted in non-decreasing order. This operation allows for the expansion of the array and provides flexibility in handling larger integers by breaking them down into smaller integers that contribute to sorting the entire array more effectively.

Examples

Example 1

Input:

nums = [3,9,3]

Output:

2

Explanation:

Here are the steps to sort the array in non-decreasing order:
- From [3,9,3], replace the 9 with 3 and 6 so the array becomes [3,3,6,3]
- From [3,3,6,3], replace the 6 with 3 and 3 so the array becomes [3,3,3,3,3]
There are 2 steps to sort the array in non-decreasing order. Therefore, we return 2.

Example 2

Input:

nums = [1,2,3,4,5]

Output:

0

Explanation:

The array is already in non-decreasing order. Therefore, we return 0.

Constraints

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109

Approach and Intuition

  1. Initial Understanding

    • Suppose you have an array where elements are not in non-decreasing order. The task is to use the given operation (split one element into two sum components) to help sort the array.
    • An array is considered sorted in non-decreasing order if every subsequent element is greater than or equal to the preceding one (i.e., the sequence either remains constant or increases).
  2. Breaking Down the Examples

    • For example, if the array is [3,9,3], breaking down 9 into [3,6] and further breaking 6 into [3,3] helps in making the array non-decreasing as [3,3,3,3,3]. Each operation contributes to achieving a more sorted structure by reducing larger unsorted elements into components that fit better in a sorted order.
  3. Using Operations Strategically

    • The key is to identify which operations minimize the total disruptions while pushing the array towards being sorted. For higher numbers that are out of place (either larger than subsequent numbers or causing a decrease in sequence), breaking them down into components that are less than or equal to the next number in the sequence is advantageous.
  4. Counting Needed Operations

    • Assess each element and determine if it needs to be operated on (i.e., if it's out of order when compared to the next one). If so, execute the operation by splitting the number into smaller or equal parts that align better with the subsequent numbers.
    • Increment the operation count each time an element is handled.
  5. Optimal Check Before Operations

    • Before applying any operations, it's efficient to initially check if the array is already sorted. This can save computational time and operations.

This methodical breakdown into potential smaller sub-problems (each operation treated as sorting a part of the array) indicates a step-wise refinement approach, where sorting is achieved progressively, albeit the array's length might increase transiently during the process. Sorting algorithms can be employed after this to further enhance or verify the output.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    long long minimumReplacements(vector<int>& array) {
        long long total = 0;
        int length = array.size();
        
        for (int index = length - 2; index >= 0; index--) {
            if (array[index] <= array[index + 1]) {
                continue;
            }

            long long splits = ceil(double(array[index]) / array[index + 1]);
            total += splits - 1;
            array[index] = array[index] / splits;
        }

        return total;
    }
};

In the C++ solution for calculating the minimum replacements needed to sort an array in non-decreasing order, you'll find a concise and efficient approach. The method involves iterating backward through the array to evaluate each element compared to the next one. If the element is greater than the one following it, calculations are performed to determine the number of splits required to reduce its value until it is less than or equal to the next element. These necessary splits minus one equate to the replacements needed to sort the array element into place.

Key details of the implementation include:

  • Using the ceil function to determine the necessary number of times an element needs to be divided by the next element to ensure all values remain sorted.
  • Summing the calculated splits to compile the total number of replacements needed across the array.
  • Iterating from the second last to the first element to ensure each is adjusted based on the already evaluated elements that follow.

This approach guarantees that the function efficiently calculates and returns the total number of replacements necessary to make the array non-decreasing from any initial configuration.

java
class Solution {
    public long findMinimumReplacements(int[] array) {
        long totalReplaces = 0;
        int length = array.length;

        for (int index = length - 2; index >= 0; index--) {
            if (array[index] <= array[index + 1]) {
                continue;
            }

            long parts = (long) (array[index] + array[index + 1] - 1) / (long) array[index + 1];
            totalReplaces += parts - 1;
            array[index] = array[index] / (int) parts;
        }

        return totalReplaces;
    }
}

This solution focuses on the problem of finding the minimum number of replacements needed to sort an array in non-decreasing order. This implementation utilizes a Java class named Solution with a method findMinimumReplacements which takes an integer array as input and returns a long integer representing the required number of operations.

The essence of the method involves iterating backwards through the array starting from the second to last element. For each element, the method checks if it is greater than the subsequent one. If it's not, it simply continues to the next iteration, implying that those parts of the array are already sorted.

However, if an element is found to be greater than the next, the method calculates how many parts the current element needs to be divided into so that each part is less than or equal to the next element. The calculation for the number of parts is:

[ \text{parts} = \left(\frac{\text{array}[index] + \text{array}[index+1] - 1}{\text{array}[index+1]}\right) ]

This essentially computes how many times the next element can fit into the current element plus some adjustment to ensure an integral result. The replacement count is incremented by parts - 1 since parts indicates how many pieces the current element needs to be broken down into, and you already have one piece (the next element).

Finally, the current element of the array is updated to its divided value to maintain the array's modified state. This approach helps reduce the value of the current element, hence gradually sorting the array while counting the minimum replacements required.

The method returns the total number of replacements once all elements are processed. This algorithm ensures efficient processing by utilizing a backward iteration and simple arithmetic operations to minimize replacements while ensuring sorting order.

python
class Solution:
    def minOps(self, data: List[int]) -> int:
        count = 0
        length = len(data)

        # Iterate backwards from the second to last element
        for idx in range(length - 2, -1, -1):
            # Continue if the current element is already smaller or equal
            if data[idx] <= data[idx + 1]:
                continue
            
            # Calculate the number of parts the current element should be divided into
            parts = (data[idx] + data[idx + 1] - 1) // data[idx + 1]
            
            # Replacement count is parts - 1
            count += parts - 1
            
            # Adjust current element value
            data[idx] = data[idx] // parts

        return count

This article elaborates on a Python function designed to determine the minimum number of replacements required to sort an array in non-decreasing order. The replacements consist of dividing an array element into smaller parts such that each subsequent number is greater than or equal to the number before it.

Examine the provided Python function:

  • The function minOps takes a list data as its parameter.
  • An integer count is initialized to track the total replacements made.
  • The length of the data list is calculated.
  • Iterate backwards through the list from the penultimate element down to the first:
    • Skip the current iteration if the current element is less than or equal to the next element.
    • If not, calculate the minimum parts the current element should be divided into to ensure the sort order. This division attempts to make the current element smaller or equal to the next element.
    • Update count to include the additional replacements needed (parts - 1).
    • The current element is then updated to the value after the division, ensuring that it's suitable for comparison with the next iteration.
  • Return the total count of replacements needed once the iteration is complete.

This approach ensures that by the end a sorted version of the array is achieved with the least number of costly replacements.

Comments

No comments yet.