3296. Minimum Number of Seconds to Make Mountain Height Zero
Problem Description
You have a mountain with a given height mountainHeight and multiple workers who can work simultaneously to reduce this height to 0. Each worker has their own working speed defined in the array workerTimes.
For each worker i, the time required to reduce the mountain height follows a specific pattern:
- To reduce height by 1: takes
workerTimes[i]seconds - To reduce height by 2: takes
workerTimes[i] + workerTimes[i] * 2seconds - To reduce height by 3: takes
workerTimes[i] + workerTimes[i] * 2 + workerTimes[i] * 3seconds - In general, to reduce height by
x: takesworkerTimes[i] * (1 + 2 + ... + x)seconds
The key insight is that this forms an arithmetic series. To reduce the height by x, worker i needs:
workerTimes[i] * (1 + 2 + ... + x) = workerTimes[i] * x * (x + 1) / 2 seconds
Since workers operate simultaneously, the total time taken is determined by when all workers collectively reduce the mountain height to 0. Each worker can reduce a different amount of height, and we need to find the optimal distribution that minimizes the total time.
The solution uses binary search on the time t. For a given time t, we calculate how much height each worker can reduce. Using the formula above, if worker i reduces height by h' in time t, then:
workerTimes[i] * h' * (h' + 1) / 2 ≤ t
Solving this quadratic inequality gives us the maximum height each worker can reduce in time t. The binary search finds the minimum time where the sum of all heights reduced by workers is at least mountainHeight.
Intuition
The key observation is that if we can reduce the mountain to height 0 in t seconds, then we can definitely do it in any time greater than t. This monotonic property immediately suggests binary search on the answer.
Why binary search on time? Consider the alternative - trying to directly calculate the optimal height distribution among workers. This becomes a complex optimization problem because each worker has different efficiency and the cost function is quadratic. However, if we fix the time t, we can easily calculate the maximum height each worker can reduce independently.
For a fixed time t, each worker works independently and we want to maximize their contribution. Given worker i has t seconds, we need to find the maximum height h' they can reduce where:
workerTimes[i] * (1 + 2 + ... + h') ≤ t
Using the arithmetic series sum formula:
workerTimes[i] * h' * (h' + 1) / 2 ≤ t
This is a quadratic inequality in h'. Rearranging:
h'² + h' - 2t/workerTimes[i] ≤ 0
Using the quadratic formula and taking the positive root:
h' ≤ (-1 + √(1 + 8t/workerTimes[i])) / 2
Which simplifies to:
h' ≤ ⌊√(2t/workerTimes[i] + 1/4) - 1/2⌋
Once we can calculate each worker's maximum contribution for a given time t, we simply sum these contributions. If the total is at least mountainHeight, then time t is sufficient. Otherwise, we need more time.
The binary search bounds are straightforward: the minimum time is close to 0, and the maximum can be estimated by considering the worst case where one slow worker does all the work. Since workerTimes[i] ≤ 10^6 and mountainHeight ≤ 10^5, the upper bound of 10^16 is safe.
Learn more about Greedy, Math, Binary Search and Heap (Priority Queue) patterns.
Solution Implementation
1from typing import List
2from math import sqrt
3
4class Solution:
5 def minNumberOfSeconds(self, mountainHeight: int, workerTimes: List[int]) -> int:
6 """
7 Find the minimum number of seconds needed to reduce the mountain to the target height.
8
9 Each worker reduces height following the pattern: 1 + 2 + 3 + ... + n units,
10 where the time taken is workerTime * (1 + 2 + ... + n) = workerTime * n * (n + 1) / 2
11
12 Args:
13 mountainHeight: The target height to reduce the mountain to
14 workerTimes: List of time coefficients for each worker
15
16 Returns:
17 Minimum seconds needed to complete the task
18 """
19
20 def can_complete_in_time(time_limit: int) -> bool:
21 """
22 Check if workers can reduce the mountain to target height within given time.
23 This is the feasible function for binary search.
24
25 Args:
26 time_limit: Maximum time allowed
27
28 Returns:
29 True if mountain can be reduced to target height within time limit
30 """
31 total_height_reduced = 0
32
33 for worker_time in workerTimes:
34 # Calculate maximum rounds this worker can complete within time_limit
35 # Using the quadratic formula solution for n
36 max_rounds = int(sqrt(2 * time_limit / worker_time + 0.25) - 0.5)
37 total_height_reduced += max_rounds
38
39 return total_height_reduced >= mountainHeight
40
41 # Binary search using standard template to find minimum valid time
42 left, right = 1, 10**16
43 first_true_index = -1
44
45 while left <= right:
46 mid = (left + right) // 2
47 if can_complete_in_time(mid):
48 first_true_index = mid
49 right = mid - 1 # Found valid time, try smaller
50 else:
51 left = mid + 1 # Need more time
52
53 return first_true_index
541class Solution {
2 private int mountainHeight;
3 private int[] workerTimes;
4
5 /**
6 * Finds the minimum number of seconds needed for workers to reduce the mountain to ground level.
7 * Uses binary search to find the optimal time.
8 *
9 * @param mountainHeight The initial height of the mountain
10 * @param workerTimes Array where workerTimes[i] represents the time for worker i to reduce height by 1
11 * @return The minimum number of seconds needed
12 */
13 public long minNumberOfSeconds(int mountainHeight, int[] workerTimes) {
14 this.mountainHeight = mountainHeight;
15 this.workerTimes = workerTimes;
16
17 // Binary search using standard template
18 long left = 1;
19 long right = (long) 1e16;
20 long firstTrueIndex = -1;
21
22 while (left <= right) {
23 long mid = left + (right - left) / 2;
24
25 if (canCompleteInTime(mid)) {
26 // Feasible: can complete in 'mid' seconds
27 firstTrueIndex = mid;
28 right = mid - 1; // Try to find smaller time
29 } else {
30 // Not feasible: need more time
31 left = mid + 1;
32 }
33 }
34
35 return firstTrueIndex;
36 }
37
38 /**
39 * Checks if workers can reduce the mountain to ground level within given time.
40 * Each worker reduces height following arithmetic progression: 1st unit takes workerTime[i],
41 * 2nd unit takes 2*workerTime[i], nth unit takes n*workerTime[i].
42 * Total time for n units: workerTime[i] * (1 + 2 + ... + n) = workerTime[i] * n * (n + 1) / 2
43 *
44 * @param timeLimit The time limit to check
45 * @return true if the mountain can be reduced within timeLimit, false otherwise
46 */
47 private boolean canCompleteInTime(long timeLimit) {
48 long totalHeightReduced = 0;
49
50 for (int workerTime : workerTimes) {
51 // For each worker, calculate maximum height they can reduce in timeLimit
52 // Using formula: workerTime * n * (n + 1) / 2 <= timeLimit
53 // Solving for n: n = (-1 + sqrt(1 + 8 * timeLimit / workerTime)) / 2
54 // Simplified: n = sqrt(2 * timeLimit / workerTime + 0.25) - 0.5
55 long maxHeightByWorker = (long) (Math.sqrt(timeLimit * 2.0 / workerTime + 0.25) - 0.5);
56 totalHeightReduced += maxHeightByWorker;
57 }
58
59 // Check if total height reduced by all workers meets the requirement
60 return totalHeightReduced >= mountainHeight;
61 }
62}
631class Solution {
2public:
3 long long minNumberOfSeconds(int mountainHeight, vector<int>& workerTimes) {
4 using ll = long long;
5
6 // Binary search bounds: minimum 1 second, maximum 10^16 seconds
7 ll left = 1;
8 ll right = 1e16;
9
10 // Lambda function to check if given time is sufficient to reduce mountain to 0
11 auto canCompleteInTime = [&](ll timeLimit) -> bool {
12 ll totalHeightReduced = 0;
13
14 // For each worker, calculate how much height they can reduce in given time
15 for (int& workerTime : workerTimes) {
16 // Worker reduces height by 1, 2, 3, ... units
17 // Time taken: workerTime * (1 + 2 + 3 + ... + n) = workerTime * n * (n + 1) / 2
18 // Given timeLimit, solve for n: workerTime * n * (n + 1) / 2 <= timeLimit
19 // This gives us a quadratic equation: n^2 + n - 2*timeLimit/workerTime <= 0
20 // Using quadratic formula: n = (-1 + sqrt(1 + 8*timeLimit/workerTime)) / 2
21 // Simplified calculation below
22 totalHeightReduced += static_cast<ll>(sqrt(timeLimit * 2.0 / workerTime + 0.25) - 0.5);
23 }
24
25 // Check if total height reduced meets or exceeds the mountain height
26 return totalHeightReduced >= mountainHeight;
27 };
28
29 // Binary search using standard template
30 ll firstTrueIndex = -1;
31
32 while (left <= right) {
33 ll mid = left + (right - left) / 2;
34
35 if (canCompleteInTime(mid)) {
36 // Feasible: can complete in 'mid' seconds
37 firstTrueIndex = mid;
38 right = mid - 1; // Try to find smaller time
39 } else {
40 // Not feasible: need more time
41 left = mid + 1;
42 }
43 }
44
45 return firstTrueIndex;
46 }
47};
481/**
2 * Calculates the minimum number of seconds needed for workers to reduce a mountain to height 0.
3 * Each worker reduces the mountain height by 1, 2, 3, ... units in successive operations,
4 * taking workerTime * (1 + 2 + ... + k) seconds for k operations.
5 *
6 * @param mountainHeight - The initial height of the mountain to be reduced
7 * @param workerTimes - Array where workerTimes[i] is the time multiplier for worker i
8 * @returns The minimum number of seconds needed to reduce the mountain to height 0
9 */
10function minNumberOfSeconds(mountainHeight: number, workerTimes: number[]): number {
11 /**
12 * Checks if the given time is sufficient for workers to reduce the mountain.
13 * Uses the formula: time = workerTime * k * (k + 1) / 2 for k operations
14 * Solving for k: k = floor((-1 + sqrt(1 + 8 * time / workerTime)) / 2)
15 *
16 * @param timeLimit - The time limit to check
17 * @returns true if workers can reduce the mountain within the time limit
18 */
19 const canCompleteInTime = (timeLimit: bigint): boolean => {
20 let totalHeightReduced = BigInt(0);
21
22 for (const workerTime of workerTimes) {
23 // Calculate maximum operations this worker can perform within time limit
24 // Using quadratic formula: k = (-0.5 + sqrt(0.25 + 2 * time / workerTime))
25 const maxOperations = Math.floor(
26 Math.sqrt((Number(timeLimit) * 2.0) / workerTime + 0.25) - 0.5
27 );
28 totalHeightReduced += BigInt(maxOperations);
29 }
30
31 return totalHeightReduced >= BigInt(mountainHeight);
32 };
33
34 // Binary search using standard template
35 let left = BigInt(1);
36 let right = BigInt(1e16);
37 let firstTrueIndex = BigInt(-1);
38
39 while (left <= right) {
40 const mid = (left + right) / BigInt(2);
41
42 if (canCompleteInTime(mid)) {
43 // Feasible: can complete in 'mid' seconds
44 firstTrueIndex = mid;
45 right = mid - BigInt(1); // Try to find smaller time
46 } else {
47 // Not feasible: need more time
48 left = mid + BigInt(1);
49 }
50 }
51
52 return Number(firstTrueIndex);
53}
54Solution Approach
The solution implements a binary search to find the minimum time required. Here's how the implementation works:
Binary Search Setup:
We use the standard binary search template to find the first time where the condition becomes True. The feasible condition is: "can workers reduce the mountain in time t?" This creates a pattern like [false, false, ..., true, true, ...] and we find the first true.
left, right = 1, 10**16 first_true_index = -1 while left <= right: mid = (left + right) // 2 if can_complete_in_time(mid): first_true_index = mid right = mid - 1 # Found valid time, try smaller else: left = mid + 1 # Need more time return first_true_index
Check Function:
The check(t) function determines if time t is sufficient for workers to reduce the mountain to height 0:
-
Initialize a counter
h = 0to track the total height reduction -
For each worker with time
workerTimes[i], calculate the maximum height they can reduce using the formula:h += int(sqrt(2 * t / wt + 1 / 4) - 1 / 2)This formula comes from solving the quadratic inequality:
wt * h' * (h' + 1) / 2 ≤ tWhich gives us:
h' ≤ √(2t/wt + 1/4) - 1/2 -
Return
Trueif the total height reductionh >= mountainHeight
Why This Formula Works:
Given a worker needs wt * h' * (h' + 1) / 2 seconds to reduce height by h', we rearrange to find the maximum h' possible in time t:
- Start with:
wt * h' * (h' + 1) / 2 ≤ t - Multiply by 2:
wt * h' * (h' + 1) ≤ 2t - Expand:
wt * h'² + wt * h' ≤ 2t - Rearrange:
h'² + h' - 2t/wt ≤ 0 - Complete the square:
(h' + 1/2)² ≤ 2t/wt + 1/4 - Take square root:
h' + 1/2 ≤ √(2t/wt + 1/4) - Solve for h':
h' ≤ √(2t/wt + 1/4) - 1/2
Binary Search Execution:
The template efficiently finds the minimum time where can_complete_in_time(t) returns True:
- Initialize
first_true_index = -1to track the answer - Use
while left <= rightloop structure - When feasible (
can_complete_in_time(mid)is true), record the answer and search left withright = mid - 1 - When not feasible, search right with
left = mid + 1
The time complexity is O(n * log(10^16)) where n is the number of workers, as we perform the check function O(log(10^16)) times, and each check takes O(n) time to iterate through all workers.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a small example with mountainHeight = 10 and workerTimes = [2, 4].
Step 1: Understanding Worker Capabilities
Worker 0 (time = 2):
- Reduce by 1: takes 2×1 = 2 seconds
- Reduce by 2: takes 2×(1+2) = 6 seconds
- Reduce by 3: takes 2×(1+2+3) = 12 seconds
- Reduce by 4: takes 2×(1+2+3+4) = 20 seconds
Worker 1 (time = 4):
- Reduce by 1: takes 4×1 = 4 seconds
- Reduce by 2: takes 4×(1+2) = 12 seconds
- Reduce by 3: takes 4×(1+2+3) = 24 seconds
Step 2: Binary Search Process
We binary search on time from 0 to 10^16. Let's check some key time values:
Check t = 10:
- Worker 0: Using formula
h' ≤ √(2×10/2 + 1/4) - 1/2 = √(10.25) - 0.5 ≈ 2.7, so can reduce 2 units - Worker 1: Using formula
h' ≤ √(2×10/4 + 1/4) - 1/2 = √(5.25) - 0.5 ≈ 1.8, so can reduce 1 unit - Total reduction: 2 + 1 = 3 < 10 ❌ (not enough)
Check t = 20:
- Worker 0:
h' ≤ √(2×20/2 + 1/4) - 1/2 = √(20.25) - 0.5 ≈ 4.0, so can reduce 4 units - Worker 1:
h' ≤ √(2×20/4 + 1/4) - 1/2 = √(10.25) - 0.5 ≈ 2.7, so can reduce 2 units - Total reduction: 4 + 2 = 6 < 10 ❌ (not enough)
Check t = 40:
- Worker 0:
h' ≤ √(2×40/2 + 1/4) - 1/2 = √(40.25) - 0.5 ≈ 5.8, so can reduce 5 units - Worker 1:
h' ≤ √(2×40/4 + 1/4) - 1/2 = √(20.25) - 0.5 ≈ 4.0, so can reduce 4 units - Total reduction: 5 + 4 = 9 < 10 ❌ (not enough)
Check t = 42:
- Worker 0:
h' ≤ √(2×42/2 + 1/4) - 1/2 = √(42.25) - 0.5 ≈ 6.0, so can reduce 6 units - Worker 1:
h' ≤ √(2×42/4 + 1/4) - 1/2 = √(21.25) - 0.5 ≈ 4.1, so can reduce 4 units - Total reduction: 6 + 4 = 10 ✓ (sufficient!)
Step 3: Verification
Let's verify t = 42 is correct:
- Worker 0 reduces 6 units: takes 2×(1+2+3+4+5+6) = 2×21 = 42 seconds
- Worker 1 reduces 4 units: takes 4×(1+2+3+4) = 4×10 = 40 seconds
- Both finish within 42 seconds, and 6 + 4 = 10 (mountain fully reduced)
Binary search continues narrowing down between values where the check fails and succeeds, ultimately finding that 42 is the minimum time needed.
Time and Space Complexity
Time Complexity: O(n × log M), where n is the number of workers (length of workerTimes), and M is the upper bound of the binary search range, which is 10^16 in this problem.
The analysis breaks down as follows:
- The
bisect_leftfunction performs a binary search over the range[0, 10^16), which requiresO(log M)iterations whereM = 10^16 - For each iteration of the binary search, the
checkfunction is called - Inside the
checkfunction, we iterate through allnworkers inworkerTimes, performing a constant-time calculation (square root and arithmetic operations) for each worker - Therefore, each call to
checktakesO(n)time - The total time complexity is
O(n) × O(log M) = O(n × log M)
Space Complexity: O(1)
The space analysis:
- The
checkfunction only uses a constant amount of extra space for the variablehand loop variable - The binary search itself only requires constant space for maintaining search boundaries
- No additional data structures are created that scale with the input size
- Therefore, the overall space complexity is
O(1)(constant space)
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Using Wrong Binary Search Template Variant
Pitfall: Using while left < right with right = mid instead of the standard template:
# WRONG: Non-standard variant while left < right: mid = (left + right) // 2 if can_complete_in_time(mid): right = mid else: left = mid + 1 return left
Solution: Use the standard template with first_true_index:
# CORRECT: Standard template first_true_index = -1 while left <= right: mid = (left + right) // 2 if can_complete_in_time(mid): first_true_index = mid right = mid - 1 else: left = mid + 1 return first_true_index
2. Integer Overflow in Binary Search Upper Bound
Pitfall: Using an inadequate upper bound for binary search can lead to incorrect results for large inputs. The formula workerTime * n * (n + 1) / 2 grows quadratically, and with large mountainHeight and workerTimes, the required time can be substantial.
Solution: Use a sufficiently large upper bound. A safe approach is to calculate the worst-case scenario:
# Calculate a proper upper bound
max_worker_time = max(workerTimes)
# Worst case: single slowest worker does all the work
upper_bound = max_worker_time * mountainHeight * (mountainHeight + 1) // 2
2. Floating Point Precision Errors
Pitfall: The quadratic formula involves square roots and division, which can introduce floating-point precision errors:
# Potential precision issues
max_rounds = int(sqrt(2 * time_limit / worker_time + 0.25) - 0.5)
When time_limit is very large or worker_time is very small, the calculation might lose precision.
Solution: Add a small epsilon for comparison or use integer arithmetic where possible:
def can_complete_in_time(time_limit: int) -> bool:
total_height_reduced = 0
for worker_time in workerTimes:
# Binary search for max_rounds instead of using floating-point formula
left, right = 0, mountainHeight
while left < right:
mid = (left + right + 1) // 2
if worker_time * mid * (mid + 1) // 2 <= time_limit:
left = mid
else:
right = mid - 1
total_height_reduced += left
return total_height_reduced >= mountainHeight
3. Incorrect Quadratic Formula Application
Pitfall: Misapplying the quadratic formula or using the wrong root. The inequality wt * h * (h + 1) / 2 ≤ t leads to a quadratic equation, and choosing the wrong root or making algebraic errors is common.
Solution: Verify the formula derivation and always take the positive root:
# Correct formula with explicit steps
discriminant = 1 + 8 * time_limit / worker_time
if discriminant < 0:
max_rounds = 0
else:
# We need the positive root: (-1 + sqrt(discriminant)) / 2
max_rounds = int((-1 + sqrt(discriminant)) / 2)
4. Division by Zero
Pitfall: If any workerTimes[i] is 0, division by zero occurs in the formula.
Solution: Add validation for edge cases:
def can_complete_in_time(time_limit: int) -> bool:
total_height_reduced = 0
for worker_time in workerTimes:
if worker_time == 0:
# Worker with 0 time can reduce infinite height instantly
return True
max_rounds = int(sqrt(2 * time_limit / worker_time + 0.25) - 0.5)
total_height_reduced += max_rounds
return total_height_reduced >= mountainHeight
5. Early Termination Optimization Missing
Pitfall: Continuing to calculate even after we've already reduced enough height wastes computation.
Solution: Add early termination:
def can_complete_in_time(time_limit: int) -> bool:
total_height_reduced = 0
for worker_time in workerTimes:
max_rounds = int(sqrt(2 * time_limit / worker_time + 0.25) - 0.5)
total_height_reduced += max_rounds
# Early termination if we've already reduced enough
if total_height_reduced >= mountainHeight:
return True
return total_height_reduced >= mountainHeight
In a binary min heap, the maximum element can be found in:
Recommended Readings
Greedy Introduction div class responsive iframe iframe src https www youtube com embed WTslqPbj7I title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture web share allowfullscreen iframe div When do we use greedy Greedy algorithms tend to solve optimization problems Typically they will ask you to calculate the max min of some value Commonly you may see this phrased in the problem as max min longest shortest largest smallest etc These keywords can be identified by just scanning
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
https assets algo monster cover_photos Binary_Search svg Binary Search Intuition Binary search is an efficient array search algorithm It works by narrowing down the search range by half each time If you have looked up a word in a physical dictionary you've already used binary search in real life Let's
Want a Structured Path to Master System Design Too? Don’t Miss This!