Maximum Running Time of N Computers
With k batteries (any one can power any computer, swappable instantly), maximize minutes all n computers can run — binary search on answer.
4 min read
binary-search
Problem#
n computers, k batteries with capacities batteries[i]. At any second, any battery can power one computer (or be idle); swaps are free. Return the maximum number of minutes all n computers can run simultaneously.
Examples#
n = 2, batteries = [3,3,3]→4n = 2, batteries = [1,1,1,1]→2
Hints#
Hint 1
For a candidate minute count
t, each battery contributes min(t, capacity) to the pool. Feasible iff total ≥ n * t. Approach#
Binary search on t. The feasibility predicate sums min(t, c) and compares to n * t.
Solution#
class Solution {public: long long maxRunTime(int n, vector<int>& batteries) { auto feasible = [&](long long t) { long long total = 0; for (int c : batteries) total += min((long long)c, t); return total >= (long long)n * t; }; long long lo = 1, hi = accumulate(batteries.begin(), batteries.end(), 0LL) / n; while (lo < hi) { long long mid = lo + (hi - lo + 1) / 2; if (feasible(mid)) lo = mid; else hi = mid - 1; } return lo; }};func maxRunTime(n int, batteries []int) int64 { feasible := func(t int64) bool { var total int64 for _, c := range batteries { if int64(c) < t { total += int64(c) } else { total += t } } return total >= int64(n)*t } var sum int64 for _, c := range batteries { sum += int64(c) } lo, hi := int64(1), sum/int64(n) for lo < hi { mid := lo + (hi-lo+1)/2 if feasible(mid) { lo = mid } else { hi = mid - 1 } } return lo}from typing import List
class Solution: def maxRunTime(self, n: int, batteries: List[int]) -> int: def feasible(t: int) -> bool: total = 0 for c in batteries: total += min(c, t) return total >= n * t
lo, hi = 1, sum(batteries) // n while lo < hi: mid = lo + (hi - lo + 1) // 2 if feasible(mid): lo = mid else: hi = mid - 1 return lofunction maxRunTime(n, batteries) { const feasible = (t) => { let total = 0n; for (const c of batteries) { const cb = BigInt(c); total += cb < t ? cb : t; } return total >= BigInt(n) * t; }; let sum = 0n; for (const c of batteries) sum += BigInt(c); let lo = 1n, hi = sum / BigInt(n); while (lo < hi) { const mid = lo + (hi - lo + 1n) / 2n; if (feasible(mid)) lo = mid; else hi = mid - 1n; } return Number(lo);}class Solution { public long maxRunTime(int n, int[] batteries) { long sum = 0; for (int c : batteries) sum += c; long lo = 1, hi = sum / n; while (lo < hi) { long mid = lo + (hi - lo + 1) / 2; if (feasible(batteries, n, mid)) lo = mid; else hi = mid - 1; } return lo; }
private boolean feasible(int[] batteries, int n, long t) { long total = 0; for (int c : batteries) total += Math.min((long) c, t); return total >= (long) n * t; }}function maxRunTime(n: number, batteries: number[]): number { const feasible = (t: bigint): boolean => { let total = 0n; for (const c of batteries) { const cb = BigInt(c); total += cb < t ? cb : t; } return total >= BigInt(n) * t; }; let sum = 0n; for (const c of batteries) sum += BigInt(c); let lo = 1n, hi = sum / BigInt(n); while (lo < hi) { const mid = lo + (hi - lo + 1n) / 2n; if (feasible(mid)) lo = mid; else hi = mid - 1n; } return Number(lo);}Editorial#
The non-obvious capacity-clipping min(t, c) is the elegance: a battery with c > t contributes only t (it can’t help past minute t); a battery with c <= t contributes c. The total contribution must cover n * t minute-units of demand.
Complexity#
- Time: O(k log totalPower).
- Space: O(1).
Concept revision#
Related#