Maximize the Minimum Powered City
HardPrompt
You are given a 0-indexed integer array stations of length n, where stations[i] represents the number of power stations in the ith city.
Each power station can provide power to every city in a fixed range. In other words, if the range is denoted by r, then a power station at city i can provide power to all cities j such that |i - j| <= r and 0 <= i, j <= n - 1.
- Note that
|x|denotes absolute value. For example,|7 - 5| = 2and|3 - 10| = 7.
The power of a city is the total number of power stations it is being provided power from.
The government has sanctioned building k more power stations, each of which can be built in any city, and have the same range as the pre-existing ones.
Given the two integers r and k, return the maximum possible minimum power of a city, if the additional power stations are built optimally.
Note that you can build the k power stations in multiple cities.
Example 1:
Input: stations = [1,2,4,5,0], r = 1, k = 2
Output: 5
Explanation:
One of the optimal ways is to install both the power stations at city 1.
So stations will become [1,4,4,5,0].
- City 0 is provided by 1 + 4 = 5 power stations.
- City 1 is provided by 1 + 4 + 4 = 9 power stations.
- City 2 is provided by 4 + 4 + 5 = 13 power stations.
- City 3 is provided by 5 + 4 = 9 power stations.
- City 4 is provided by 5 + 0 = 5 power stations.
So the minimum power of a city is 5.
Since it is not possible to obtain a larger power, we return 5.Example 2:
Input: stations = [4,4,4,4], r = 0, k = 3
Output: 4
Explanation:
It can be proved that we cannot make the minimum power of a city greater than 4.
Constraints:
n == stations.length1 <= n <= 1050 <= stations[i] <= 1050 <= r <= n - 10 <= k <= 109
Approaches
2 approaches with complexity analysis and trade-offs.
This is the optimal approach, building upon the binary search framework. The key improvement is optimizing the check(x) function to run in linear time, O(n). This is achieved by avoiding the repeated power calculations. We first pre-calculate the initial power of every city. Then, as we iterate through the cities and add new stations, we use a difference array (or a similar sliding window technique) to efficiently track the additional power (boost) these new stations provide to subsequent cities.
Algorithm
- Define a search range for the minimum power, from
0tosum(stations) + k. - Perform binary search on this range. For each
midvalue:
- Call an efficient
check(mid)function. - The
check(targetPower)function works as follows:- In O(n), pre-calculate
initialPower[i]for alliusing a prefix sum array onstations. - Initialize a difference array
boostDiffof sizen+1to all zeros. - Initialize
stationsLeft = kandcurrentBoost = 0. - Iterate through each city
ifrom0ton-1: a. Update the power from new stations:currentBoost += boostDiff[i]. b. Calculate total power:totalPower = initialPower[i] + currentBoost. c. IftotalPower < targetPower, calculateneededstations. d. Ifneeded > stationsLeft, returnfalse. e. DecrementstationsLeftbyneeded. f. IncreasecurrentBoostbyneededas these new stations help cityiimmediately. g. Schedule the boost to be removed after its effect ends. The stations added for cityicover up to cityi+2r. So,boostDiff[i+2r+1] -= needed(with bounds check). - If the loop completes, return
true.
- In O(n), pre-calculate
- If
check(mid)is true, try for a higher power:ans = mid,low = mid + 1. - If
check(mid)is false, we need a lower power:high = mid - 1. - Return the final
ans.
Walkthrough
The check(targetPower) function is optimized as follows:
- Pre-computation: Calculate the initial power of every city based on the original
stationsarray. This can be done in O(n) time using a prefix sum array.initialPower[i] = sum(stations[j])forjin[i-r, i+r]. - Greedy Iteration with Efficient Updates: We iterate through cities from
i = 0ton-1. We maintain a variablecurrentBoostwhich represents the extra power cityireceives from all the new stations added for previous cities (j < i). - When we add
neededstations for cityi, they are placed ati+rand provide power to cities in the range[i, i+2r]. This means thecurrentBoostincreases byneededstarting from cityi. This boost effect stops after cityi+2r. We can model this efficiently using a difference array,boostDiff. When we addneededstations for cityi, we've already addedneededtocurrentBoost. To stop this effect later, we schedule a subtraction:boostDiff[i + 2*r + 1] -= needed. - At each city
i, we updatecurrentBoostby addingboostDiff[i]. The total power is theninitialPower[i] + currentBoost. If this is less thantargetPower, we add new stations and update our data structures as described.
Here is the efficient check function implementation:
private boolean check(long targetPower, int[] stations, int r, long k) { int n = stations.length; long[] prefixSum = new long[n + 1]; for (int i = 0; i < n; i++) { prefixSum[i + 1] = prefixSum[i] + stations[i]; } long[] initialPower = new long[n]; for (int i = 0; i < n; i++) { int left = Math.max(0, i - r); int right = Math.min(n - 1, i + r); initialPower[i] = prefixSum[right + 1] - prefixSum[left]; } long stationsLeft = k; long[] boostDiff = new long[n + 1]; long currentBoost = 0; for (int i = 0; i < n; i++) { currentBoost += boostDiff[i]; long currentTotalPower = initialPower[i] + currentBoost; if (currentTotalPower < targetPower) { long needed = targetPower - currentTotalPower; if (needed > stationsLeft) { return false; } stationsLeft -= needed; currentBoost += needed; int endEffectIndex = i + 2 * r + 1; if (endEffectIndex < n) { boostDiff[endEffectIndex] -= needed; } } } return true;}Complexity
Time
O(n * log(S)) where `n` is the number of cities and `S` is the search space size. The `check` function is optimized to O(n) using prefix sums and a difference array. The binary search contributes the `log(S)` factor.
Space
O(n) to store the prefix sum array, the initial power array, and the difference array for the boost.
Trade-offs
Pros
Highly efficient and meets the time constraints of the problem.
It's the standard and optimal way to solve this category of problems.
Cons
The logic for the
checkfunction, especially the use of the difference array to track power boosts, is more complex to understand and implement correctly.
Solutions
Solution
class Solution {private long[] s;private long[] d;private int n;public long maxPower(int[] stations, int r, int k) { n = stations.length; d = new long[n + 1]; s = new long[n + 1]; for (int i = 0; i < n; ++i) { int left = Math.max(0, i - r), right = Math.min(i + r, n - 1); d[left] += stations[i]; d[right + 1] -= stations[i]; } s[0] = d[0]; for (int i = 1; i < n + 1; ++i) { s[i] = s[i - 1] + d[i]; } long left = 0, right = 1 l << 40; while (left < right) { long mid = (left + right + 1) >>> 1; if (check(mid, r, k)) { left = mid; } else { right = mid - 1; } } return left; }private boolean check(long x, int r, int k) { Arrays.fill(d, 0); long t = 0; for (int i = 0; i < n; ++i) { t += d[i]; long dist = x - (s[i] + t); if (dist > 0) { if (k < dist) { return false; } k -= dist; int j = Math.min(i + r, n - 1); int left = Math.max(0, j - r), right = Math.min(j + r, n - 1); d[left] += dist; d[right + 1] -= dist; t += dist; } } return true; }}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.