# 27.07.2023 [2141. Maximum Running Time of N Computers]
Maximum time to use `n` batteries in parallel
27.07.2023
2141. Maximum Running Time of N Computers hard
blog post
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/288
Problem TLDR
Maximum time to use n
batteries in parallel
Hint 1
Batteries 5 5 5
is equal to 1 2 3 4 5
to run 3
computers for 5
minutes.
Hint 2
Batteries are swapped instantly, so we can drain all 1 2 3 4 5
with just 3
computers, but if a pack is 1 2 3 4 100
we can only drain 5
from the last 100
battery. (or less)
Hint 3
Energy of 5 5 5
is 15
to run for 5
minutes.
Energy in 1 2 3 4 100
is 1+2+3+4+5
when run for 5
minutes.
Energy in 1 2 3 4 100
is 1+2+3+4+4
when run for 4
minutes.
Energy in 1 2 3 4 100
is 1+2+3+3+3
when run for 3
minutes.
Intuition
The Binary Search idea is first to mind, as with growth of run time the function of canRun
do the flip.
However, to detect if we canRun
the given time
is not so trivial.
We can use all batteries by swapping them every minute. To use 5
batteries in 3
computers, we can first use the max capacity and change others:
1 2 3 4 5
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
In this example, time = 5
. Or we can have just 3
batteries with capacity of 5
each: 5 5 5
. What if we add another battery:
1 2 3 4 5 9
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
Time
becomes 7
, or we can have 7 7 7
battery pack with total energy = 3 * 7 = 21
. And we don’t use 1
yet.
Let’s observe the energy for the time = 7
:
1 2 3 4 5 9
* 1 1 1 1 1
1 1 1 1 1
1 1 1 1
1 1 1
1 1
1
1
We didn’t use 1
, but had we another 1
the total energy will be 21 + 1 + 1 + 1(from 9)
or 24
, which is equal to 3 * 8
, or time = 8
.
So, by this diagram, we can take at most time
power units from each battery.
So, our function canRun(time)
is: energy(time) >= time * n
. Energy is a sum of all batteries running at most time
.
Approach
Binary Search:
inclusive
lo
&hi
last check
lo == hi
compute result
res = mid
boundaries
lo = mid + 1
,hi = mid - 1
Complexity
Time complexity:
O(nlog(n))Space complexity:
O(1)
Code
fun maxRunTime(n: Int, batteries: IntArray): Long {
// n=3 1 2 3 4 5 6 7 9
// time = 4
// we need 4 4 4, take 1 2 3 4 4 4 4 4
// time = 5
// we need 5 5 5, take 1 2 3 4 5 5 5 5
// n=3 3 3 3 80
// time = 1 1 1 1 1 vs 1 1 1
// time = 2 2 2 2 2 vs 2 2 2
// time = 3 3 3 3 3 vs 3 3 3
// time = 4 3 3 3 4 (13) vs 4 4 4 (16)
// time = 5 3 3 3 5 (14) vs 5 5 5 (15)
// time = 6 3 3 3 6 (15) vs 6 6 6 (18)
var lo = 0L
var hi = batteries.asSequence().map { it.toLong() }.sum() ?: 0L
var res = 0L
while (lo <= hi) {
val mid = lo + (hi - lo) / 2L
val canRun = n * mid <= batteries.asSequence().map { minOf(it.toLong(), mid) }.sum()!!
if (canRun) {
res = mid
lo = mid + 1L
} else hi = mid - 1L
}
return res
}