Minimum Replacements to Sort the Array

Replace each oversized element with k equal parts ≤ next; walk right-to-left tracking the running ceiling.

Hard
Time O(n) Space O(1)
LeetCode
4 min read
greedy math

Problem#

Replace any element with a sequence of two or more positive integers summing to it (one operation). Return the minimum operations to make the array non-decreasing.

Examples#

  • nums = [3,9,3]2 (split 9 into 3+3+3)
  • nums = [1,2,3,4,5]0

Hints#

Hint 1
Process right-to-left. The current “ceiling” is the maximum first-part of any future split. For nums[i] larger than ceiling, split into ceil(nums[i]/ceiling) parts, each as large as possible (so the first part is nums[i] / parts).

Approach#

Walk from right to left. Maintain ceiling = nums[n-1]. For each nums[i]: if nums[i] <= ceiling, set ceiling = nums[i]. Else split into parts = ceil(nums[i] / ceiling), costing parts - 1 ops; new ceiling = nums[i] / parts (floor — first part of an even split is the smallest).

Solution#

Minimum Replacements to Sort the Array
class Solution {
public:
long long minimumReplacement(vector<int>& nums) {
long long ops = 0;
long long ceiling = nums.back();
for (int i = (int)nums.size() - 2; i >= 0; --i) {
if (nums[i] <= ceiling) {
ceiling = nums[i];
} else {
long long parts = (nums[i] + ceiling - 1) / ceiling; // ceil
ops += parts - 1;
ceiling = nums[i] / parts; // first part
}
}
return ops;
}
};

Editorial#

The “first-part of an even split = nums[i] / parts” is the maximum starting value for the next position, which is what we want to relax the constraint for predecessors. Going right-to-left lets us treat the ceiling as the “max value we can leave here”.

Complexity#

  • Time: O(n).
  • Space: O(1).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.