Minimum Cost to Equalize Array
HardPrompt
You are given an integer array nums and two integers cost1 and cost2. You are allowed to perform either of the following operations any number of times:
- Choose an index
ifromnumsand increasenums[i]by1for a cost ofcost1. - Choose two different indices
i,j, fromnumsand increasenums[i]andnums[j]by1for a cost ofcost2.
Return the minimum cost required to make all elements in the array equal.
Since the answer may be very large, return it modulo 109 + 7.
Example 1:
Input: nums = [4,1], cost1 = 5, cost2 = 2
Output: 15
Explanation:
The following operations can be performed to make the values equal:
- Increase
nums[1]by 1 for a cost of 5.numsbecomes[4,2]. - Increase
nums[1]by 1 for a cost of 5.numsbecomes[4,3]. - Increase
nums[1]by 1 for a cost of 5.numsbecomes[4,4].
The total cost is 15.
Example 2:
Input: nums = [2,3,3,3,5], cost1 = 2, cost2 = 1
Output: 6
Explanation:
The following operations can be performed to make the values equal:
- Increase
nums[0]andnums[1]by 1 for a cost of 1.numsbecomes[3,4,3,3,5]. - Increase
nums[0]andnums[2]by 1 for a cost of 1.numsbecomes[4,4,4,3,5]. - Increase
nums[0]andnums[3]by 1 for a cost of 1.numsbecomes[5,4,4,4,5]. - Increase
nums[1]andnums[2]by 1 for a cost of 1.numsbecomes[5,5,5,4,5]. - Increase
nums[3]by 1 for a cost of 2.numsbecomes[5,5,5,5,5].
The total cost is 6.
Example 3:
Input: nums = [3,5,3], cost1 = 1, cost2 = 3
Output: 4
Explanation:
The following operations can be performed to make the values equal:
- Increase
nums[0]by 1 for a cost of 1.numsbecomes[4,5,3]. - Increase
nums[0]by 1 for a cost of 1.numsbecomes[5,5,3]. - Increase
nums[2]by 1 for a cost of 1.numsbecomes[5,5,4]. - Increase
nums[2]by 1 for a cost of 1.numsbecomes[5,5,5].
The total cost is 4.
Constraints:
1 <= nums.length <= 1051 <= nums[i] <= 1061 <= cost1 <= 1061 <= cost2 <= 106
Approaches
2 approaches with complexity analysis and trade-offs.
The core idea is that the cost to equalize the array is a function of the target value T to which all elements are raised. This cost function, cost(T), is convex (or has a 'bowl' shape). This property allows us to efficiently search for the minimum cost using ternary search.
Algorithm
- Handle Simple Case: If performing two single-increment operations is cheaper or equal to one double-increment operation (
2 * cost1 <= cost2), it's always optimal to only use single increments. The target value should be the minimum possible, which ismax(nums). The total cost issum(max(nums) - nums[i]) * cost1. - Convex Cost Function: For the main case (
2 * cost1 > cost2), the cost to make all elements equal to a target valueTcan be modeled as a functioncost(T). This function is convex, meaning it has a single minimum. This property is ideal for ternary search. - Define Search Range: We need to find the optimal
T. The minimum possibleTismax(nums). The cost will eventually increase asTgrows very large. We can set a safe upper bound for our search, for example,max(nums) + 2 * 10^6. - Ternary Search Execution: We apply ternary search on the range of
T. In each step, we take two midpoints,m1andm2, and evaluatecost(m1)andcost(m2). By comparing these costs, we can eliminate one-third of the search space. - Cost Calculation: A helper function,
calculateCost(T), is needed. It computes the cost for a given targetTby determining the total increments (S) and the maximum increments for any single element (max_inc), and then applying the optimal strategy of using paired (cost2) and single (cost1) operations. - Result: The search continues until the range is small enough. The minimum cost found during the search is the answer.
Walkthrough
First, we handle a simple case: if 2 * cost1 <= cost2, it's always optimal to use single-increment operations. The cheapest target value is max(nums), so the cost is sum(max(nums) - nums[i]) * cost1.
For the more complex case where 2 * cost1 > cost2, the paired operation is cheaper. The cost to reach a target T depends on the total increments needed (S = n*T - totalSum) and the maximum increments for any single element (max_inc = T - minVal). The cost function cost(T) can be shown to be convex. We can find the minimum of this function by performing a ternary search on the target value T.
class Solution { long cost1, cost2; int n; long totalSum; int minVal; final int MOD = 1_000_000_007; private long calculateCost(long target) { long s = (long)n * target - totalSum; long maxInc = target - minVal; long cost; if (2 * maxInc <= s) { cost = (s / 2) * cost2 + (s % 2) * cost1; } else { cost = (s - maxInc) * cost2 + (2 * maxInc - s) * cost1; } return cost; } public int minCostToEqualizeArray(int[] nums, int c1, int c2) { this.n = nums.length; if (n == 1) return 0; this.cost1 = c1; this.cost2 = c2; long maxVal = 0; minVal = Integer.MAX_VALUE; totalSum = 0; for (int num : nums) { maxVal = Math.max(maxVal, num); minVal = Math.min(minVal, num); totalSum += num; } if (2 * this.cost1 <= this.cost2) { long totalIncrements = maxVal * n - totalSum; return (int)((totalIncrements * this.cost1) % MOD); } long low = maxVal; long high = maxVal + 2 * 1000000 + 7; // A sufficiently large upper bound long minCost = Long.MAX_VALUE; while (low <= high) { long m1 = low + (high - low) / 3; long m2 = high - (high - low) / 3; if (m1 >= m2) break; long cost_m1 = calculateCost(m1); long cost_m2 = calculateCost(m2); if (cost_m1 < cost_m2) { minCost = Math.min(minCost, cost_m1); high = m2 - 1; } else { minCost = Math.min(minCost, cost_m2); low = m1 + 1; } } minCost = Math.min(minCost, calculateCost(low)); if(low < high) minCost = Math.min(minCost, calculateCost(high)); return (int)(minCost % MOD); }}Complexity
Time
O(N + log(Range)), where N is the number of elements in `nums` and `Range` is the size of the search space for the target value. The O(N) part is for pre-calculating sum, min, and max. The ternary search takes logarithmic time.
Space
O(1), as we only use a few variables to store pre-calculated values and search boundaries.
Trade-offs
Pros
Much more efficient than a linear brute-force search.
Conceptually straightforward for those familiar with ternary search.
Guaranteed to find the optimal solution for convex functions.
Cons
Slightly more complex to implement than a simple loop.
Relies on the cost function being convex. While it holds true in this problem, any slight deviation from convexity (e.g., due to floating point issues in other problems, or complex integer arithmetic) could make ternary search unreliable.
This approach involves a deeper mathematical analysis of the cost function cost(T). By understanding its properties, we can directly calculate the region where the minimum cost will occur, avoiding a search altogether. This leads to a highly efficient O(N) solution.
Algorithm
- Initial Setup: The simple case (
2 * cost1 <= cost2) and edge cases (n=1) are handled as before. An O(N) pass is used to findminVal,maxVal, andtotalSum. - Analyze Cost Function Slope: The key insight is to analyze the slope of the cost function
cost(T). The function's behavior depends on a critical pointT_critwhere2 * max_inc ≈ S.- For
T < T_crit, the slope ofcost(T)is approximately constant, determined by(n-1)*cost2 - (n-2)*cost1. - For
T > T_crit, the slope is always positive.
- For
- Two Scenarios:
- Non-decreasing Cost: If the slope for
T < T_critis non-negative (i.e.,(n-1)*cost2 >= (n-2)*cost1), the cost function is non-decreasing for allT >= maxVal. Thus, the minimum cost is achieved at the smallest possible target,T = maxVal. - Decreasing then Increasing Cost: If the slope is negative,
cost(T)first decreases and then increases after passingT_crit. The minimum must occur at or very nearT_crit. We can calculateT_crit = (totalSum - 2*minVal) / (n-2).
- Non-decreasing Cost: If the slope for
- Direct Calculation: Instead of searching, we directly identify the candidate(s) for the optimal
T. The optimalTwill bemax(maxVal, floor(T_crit)). Due to the discrete nature of the problem, we check this candidate and its successor,T_cand+1, to find the true minimum. - Final Result: The minimum of the costs calculated for these few candidates is the answer.
Walkthrough
The cost function cost(T) is piecewise. The behavior of the function changes at a critical point T_crit where 2 * max_inc (maximum increments for one element) equals S (total increments).
2 * (T - minVal) = n * T - totalSum
=> (n - 2) * T = totalSum - 2 * minVal
=> T_crit = (totalSum - 2 * minVal) / (n - 2) (for n > 2)
By analyzing the slope of cost(T) before and after this critical point, we can determine where the minimum lies without searching.
class Solution { long cost1, cost2; int n; long totalSum; int minVal; final int MOD = 1_000_000_007; private long calculateCost(long target) { if (target < minVal) return Long.MAX_VALUE; long s = (long)n * target - totalSum; long maxInc = target - minVal; long cost; if (2 * maxInc <= s) { cost = (s / 2) * cost2 + (s % 2) * cost1; } else { cost = (s - maxInc) * cost2 + (2 * maxInc - s) * cost1; } return cost; } public int minCostToEqualizeArray(int[] nums, int c1, int c2) { this.n = nums.length; if (n == 1) return 0; this.cost1 = c1; this.cost2 = c2; long maxVal = 0; minVal = Integer.MAX_VALUE; totalSum = 0; for (int num : nums) { maxVal = Math.max(maxVal, num); minVal = Math.min(minVal, num); totalSum += num; } if (2 * this.cost1 <= this.cost2) { long totalIncrements = maxVal * n - totalSum; return (int)((totalIncrements * this.cost1) % MOD); } // Case: 2 * cost1 > cost2 // Check if cost function is always non-decreasing for T >= maxVal if (n <= 2 || (long)(n - 1) * this.cost2 >= (long)(n - 2) * this.cost1) { return (int)(calculateCost(maxVal) % MOD); } else { // Cost function decreases before T_crit, then increases. long t_crit_num = totalSum - 2L * minVal; long t_crit_den = n - 2; long t_crit = t_crit_num / t_crit_den; long cand_t = Math.max(maxVal, t_crit); long cost_cand1 = calculateCost(cand_t); long cost_cand2 = calculateCost(cand_t + 1); return (int)(Math.min(cost_cand1, cost_cand2) % MOD); } }}Complexity
Time
O(N), dominated by the single pass to compute `minVal`, `maxVal`, and `totalSum`. The rest of the logic runs in constant time.
Space
O(1), as it only requires a constant amount of extra space.
Trade-offs
Pros
The most efficient solution with O(N) time complexity.
Avoids searching by directly computing the optimal target candidates.
Very fast and does not depend on the range of values in
numsfor its performance beyond the initial pass.
Cons
Requires a more involved mathematical analysis of the cost function, which can be complex to derive correctly.
The implementation logic is more intricate and has more cases to consider than the ternary search approach.
Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.