* Update giscus scroller. * Refine English docs and landing page * Sync the headings. * Update landing pages. * Update the avatar * Update Acknowledgements * Update landing pages. * Update contributors. * Update * Fix the formula formatting. * Fix the glossary. * Chapter 6. Hashing * Remove Chinese chars. * Fix headings. * Update giscus themes. * fallback to default giscus theme to solve 429 many requests error. * Add borders for callouts. * docs: sync character encoding translations * Update landing page media layout and i18n
5.7 KiB
Max Capacity Problem
!!! question
Given an array $ht$, where each element represents the height of a vertical partition. Any two partitions in the array, together with the space between them, can form a container.
The capacity of the container equals the product of its height and width (that is, its area), where the height is determined by the shorter partition and the width is the difference between the array indices of the two partitions.
Select two partitions in the array such that the capacity of the resulting container is maximized, and return that maximum capacity. An example is shown in the figure below.
The container is formed by any two partitions, so the state of this problem is the indices of the two partitions, denoted by $[i, j]$.
According to the problem statement, capacity equals height multiplied by width, where the height is determined by the shorter partition and the width is the difference between the array indices of the two partitions. Let the capacity be cap[i, j]; then we obtain the following formula:
cap[i, j] = \min(ht[i], ht[j]) \times (j - i)
Let the array length be n. Then the number of ways to choose two partitions (that is, the total number of states) is C_n^2 = \frac{n(n - 1)}{2}. The most straightforward approach is to exhaustively enumerate all states to find the maximum capacity, which has a time complexity of O(n^2).
Greedy Strategy Determination
This problem has a more efficient solution. As shown in the figure below, consider a state [i, j] where i < j and ht[i] < ht[j]. In this case, i is the shorter partition and j is the taller partition.
As shown in the figure below, if we now move the taller partition j inward toward the shorter partition i, the capacity will definitely decrease.
This is because after moving the taller partition j, the width j-i definitely decreases. Since the height is determined by the shorter partition, the height can only stay the same (i remains the shorter partition) or decrease (j becomes the shorter partition after being moved).
Conversely, only by moving the shorter partition i inward can the capacity possibly increase. Although the width will definitely decrease, the height may increase (the moved partition at i may be taller). For example, in the figure below, the area increases after moving the shorter partition.
From this, we can derive the greedy strategy for this problem: initialize two pointers at the two ends, and in each round move the pointer corresponding to the shorter partition inward until the two pointers meet.
The figure below shows the execution process of the greedy strategy.
- In the initial state, pointers
iandjare at both ends of the array. - Calculate the capacity of the current state
cap[i, j], and update the maximum capacity. - Compare the heights of partitions
iandj, and move the pointer corresponding to the shorter partition inward by one position. - Repeat steps
2.and3.untiliandjmeet.
Code Implementation
The code runs for at most n rounds, so the time complexity is $O(n)$.
Variables i, j, and res use only a constant amount of extra space, so the space complexity is $O(1)$.
[file]{max_capacity}-[class]{}-[func]{max_capacity}
Correctness Proof
The reason greedy is faster than exhaustive enumeration is that each round of greedy selection "skips" some states.
For example, in state cap[i, j], suppose i is the shorter partition and j is the taller partition. If we greedily move the shorter partition i inward by one position, the states shown in the figure below will be "skipped." This means that their capacities can no longer be checked later.
cap[i, i+1], cap[i, i+2], \dots, cap[i, j-2], cap[i, j-1]
A closer look shows that these skipped states are exactly the states obtained by moving the taller partition j inward. We have already proven that moving the taller partition inward will definitely decrease the capacity. Therefore, none of the skipped states can be the optimal solution, so skipping them does not cause us to miss the optimum.
The above analysis shows that moving the shorter partition is a "safe" operation, and that the greedy strategy is effective.













