Maximize the Minimum Powered City
HARDDescription
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
Checkout 2 different approaches to solve Maximize the Minimum Powered City. Click on different approaches to view the approach and algorithm in detail.
Binary Search with Efficient O(n) Check
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.
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 Analysis
Pros and Cons
- Highly efficient and meets the time constraints of the problem.
- It's the standard and optimal way to solve this category of problems.
- The logic for the
checkfunction, especially the use of the difference array to track power boosts, is more complex to understand and implement correctly.
Code Solutions
Checking out 3 solutions in different languages for Maximize the Minimum Powered City. Click on different languages to view the code.
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 Solution
Watch the video walkthrough for Maximize the Minimum Powered City
Similar Questions
5 related questions you might find useful
Algorithms:
Patterns:
Data Structures:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.