
Problem Statement
The problem involves an array of non-negative integers wherein each element represents the height of a bar in an elevation map. Each bar has a unit width of 1. After a rain, water can get trapped between these bars. The goal is to calculate the total volume of water that remains trapped between the bars after it stops raining. The trapping of water here is influenced by the heights of surrounding bars; water will remain trapped in a trough if there are taller or equal bars on both sides of the trough.
Examples
Example 1
Input:
height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output:
6
Explanation:
The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.
Example 2
Input:
height = [4,2,0,3,2,5]
Output:
9
Constraints
n == height.length
1 <= n <= 2 * 104
0 <= height[i] <= 105
Approach and Intuition
- The key concept here is to understand how water can get trapped between bars:
- Water gets trapped when a bar is surrounded by taller bars on both sides. The trapped water above each bar is determined by the height of the smaller of the two boundary bars (left and right side) minus the height of the current bar.
- From the examples:
- In the first example, the elevation array is
[0,1,0,2,1,0,1,3,2,1,2,1]
. We can visually analyze how water can be trapped in different troughs made up by consecutive bars. A detailed understanding points out that there are pockets at various points where water is trapped. - For the second example, the elevation array
[4,2,0,3,2,5]
makes it evident that water will trap in the mid-section where lower height bars are flanked by taller bars at both ends.
- In the first example, the elevation array is
- The constraints indicate that the length of the height array can go up to 20,000, which suggests that a time-efficient approach is necessary due to potentially large input sizes.
- Using two-pointer technique can be effective here:
- Initialize two pointers at both ends of the array.
- Compare the heights at these pointers, move the pointer pointing to the shorter bar inward, and at each step calculate if water can be trapped above the current bar based on previously seen bars.
- The computational challenge is manageable by:
- Ensuring that at each step, water trapping is checked through a local relative minimum which gets updated as we move our pointers from both ends to the middle.
- This approach effectively reduces the problem to linear time complexity, hence tackling the upper constraint limit efficiently. The actual implementation would involve maintaining a running tally of maximum height bars seen from both ends and calculating trapped water bar by bar as the pointers approach each other.
Solutions
- C++
- Java
- C
- JavaScript
- Python
class Solution {
public:
int trapRainWater(vector<int>& heights) {
int leftPtr = 0, rightPtr = heights.size() - 1;
int totalWater = 0;
int maxLeft = 0, maxRight = 0;
while (leftPtr < rightPtr) {
if (heights[leftPtr] < heights[rightPtr]) {
heights[leftPtr] >= maxLeft ? (maxLeft = heights[leftPtr])
: totalWater += (maxLeft - heights[leftPtr]);
++leftPtr;
} else {
heights[rightPtr] >= maxRight ? (maxRight = heights[rightPtr])
: totalWater += (maxRight - heights[rightPtr]);
--rightPtr;
}
}
return totalWater;
}
};
Here's a solution summary for the trapping rain water problem using C++:
The given C++ code defines a member function trapRainWater
within the Solution
class. This function is intended to calculate the total amount of water that can be trapped between bars in a list of given heights (which can be visualized similar to a histogram).
The function efficiently follows these steps:
Initialize two pointer variables,
leftPtr
andrightPtr
, to point at the beginning and the end of the heights vector respectively. Also, initializetotalWater
,maxLeft
, andmaxRight
to zero. These will hold the total water trapped, maximum height encountered from left to right, and maximum height from right to left, respectively.Use a while loop to iterate as long as
leftPtr
is less thanrightPtr
. Within each iteration, compare the heights at these pointers:If the height at
leftPtr
is less than or equal to the height atrightPtr
, compare the height atleftPtr
withmaxLeft
. If it's greater or equal, updatemaxLeft
to this new height. Otherwise, add the difference betweenmaxLeft
and the current height tototalWater
, then incrementleftPtr
to move right.If the height at
rightPtr
is less than the height atleftPtr
, undertake a similar approach by comparingrightPtr
's height withmaxRight
. UpdatemaxRight
if necessary, or calculate water trapped and then decrementrightPtr
to move left.
After the loop, the value of
totalWater
will be the total unit of water that can be trapped by the bars represented byheights
.
This approach ensures a time complexity of O(n) as each height is processed once, which makes it efficient and suitable for large input sizes. The use of two pointers here optimizes the process by eliminating the need for auxiliary space, which would be required in a naïve approach for storing left and right maximums for each index.
public class Solution {
public int calculateWater(int[] elevation) {
int start = 0, end = elevation.length - 1;
int waterTrapped = 0;
int maxLeft = 0, maxRight = 0;
while (start < end) {
if (elevation[start] < elevation[end]) {
maxLeft = Math.max(maxLeft, elevation[start]);
waterTrapped += maxLeft - elevation[start];
start++;
} else {
maxRight = Math.max(maxRight, elevation[end]);
waterTrapped += maxRight - elevation[end];
end--;
}
}
return waterTrapped;
}
}
This solution efficiently calculates the total amount of water trapped between bars on a histogram using an array of integers that represent the height of each bar. The problem is commonly referred to as "Trapping Rain Water", and the Java code provided is an embodiment of a two-pointer technique that optimizes the time complexity to O(n), where n refers to the number of bars/elevation points.
- Initialize
start
to the beginning index of theelevation
array andend
to the last index. These two pointers will help traverse the array from both ends. - Initialize
waterTrapped
to zero to maintain a running total of trapped water. - Set
maxLeft
andmaxRight
to zero. These variables will record the maximum heights encountered from the left and right sides respectively. - Use a while loop to iterate while
start
is less thanend
:- If the elevation at
start
is less than the elevation atend
, updatemaxLeft
to the greater value betweenmaxLeft
and the elevation atstart
. Calculate the water trapped atstart
by subtracting the elevation atstart
frommaxLeft
, and add this difference towaterTrapped
. Incrementstart
to move right. - If the elevation at
start
is not less than atend
, handle theend
pointer similarly but in the opposite direction. UpdatemaxRight
and subtract the elevation atend
from it, adding the difference towaterTrapped
. Decrementend
to move left.
- If the elevation at
- The function returns
waterTrapped
as the result, which is the total amount of water that can be trapped.
This approach takes advantage of the properties of water trapping where water at a particular point depends on the lesser of maximum heights to its left and right. The two-pointer technique ensures that the elevation comparisons and updates are efficiently managed for all bars.
int water_trap(int* bars, int bar_count) {
int i = 0, j = bar_count - 1;
int trapped_water = 0;
int max_left = 0, max_right = 0;
while (i < j) {
if (bars[i] < bars[j]) {
bars[i] >= max_left ? (max_left = bars[i])
: (trapped_water += (max_left - bars[i]));
++i;
} else {
bars[j] >= max_right ? (max_right = bars[j])
: (trapped_water += (max_right - bars[j]));
--j;
}
}
return trapped_water;
}
This C program calculates the amount of water that can be trapped between bars of different heights after a rainfall, which is a common computational problem. The given function water_trap
uses two pointers approach to efficiently determine the trapped water without needing additional space for storing left and right max values for each bar.
Follow these steps to understand the logic of the program:
- Initialize two pointers,
i
andj
, which start at the beginning and the end of the array respectively, and integers to store the total trapped water and the maximum height bars from the left and right (max_left
andmax_right
). - Use a
while
loop to iterate as long asi
is less thanj
. - Within the loop, compare the bars at pointers
i
andj
. - If
bars[i]
is less thanbars[j]
, check ifbars[i]
is greater than or equal tomax_left
. If true, updatemax_left
tobars[i]
. If not, add the difference betweenmax_left
andbars[i]
totrapped_water
and incrementi
. - If
bars[j]
is less than or equal tobars[i]
, apply similar logic as above but formax_right
and decrementj
.
Once the loop finishes, the trapped_water
variable contains the total volume of the trapped water, which the function returns.
This approach ensures a time complexity of O(n) and a space complexity of O(1), which is optimal for this kind of problem. Remember to provide a correct bar_count
and valid bars
array to ensure accurate computations.
var calculateWaterTrap = function (heights) {
let l = 0,
r = heights.length - 1;
let totalWater = 0;
let maxLeft = 0,
maxRight = 0;
while (l < r) {
if (heights[l] < heights[r]) {
maxLeft = Math.max(maxLeft, heights[l]);
totalWater += maxLeft - heights[l];
l++;
} else {
maxRight = Math.max(maxRight, heights[r]);
totalWater += maxRight - heights[r];
r--;
}
}
return totalWater;
};
The given JavaScript function calculateWaterTrap
determines the amount of water that can be trapped between blocks of varying heights, represented as an array. Below is an overview of how the code achieves this:
- Initialize two pointers,
l
(left) andr
(right), at the beginning and end of the array. - Set
totalWater
to track the accumulated water,maxLeft
to track the maximum height on the left, andmaxRight
to track the maximum height on the right. - While the left pointer does not cross the right:
- Compare the heights at the two pointers.
- If the height at the left pointer is less than the right:
- Update
maxLeft
with the greater value between itself and the height at the left pointer. - Add the difference between
maxLeft
and the height at the left pointer tototalWater
. - Move the left pointer to the right (increment).
- Update
- Otherwise:
- Update
maxRight
with the greater value between itself and the height at the right pointer. - Add the difference between
maxRight
and the height at the right pointer tototalWater
. - Move the right pointer to the left (decrement).
- Update
- Return the
totalWater
value, which gives the total trapped water.
This approach leverages a two-pointer strategy to efficiently solve the problem in linear time, ensuring that each block is visited once to determine the trapped water above it using its left and right maximum heights.
class Solution:
def water_trap(self, bars):
lo, hi = 0, len(bars) - 1
water_total = 0
max_left, max_right = 0, 0
while lo < hi:
if bars[lo] < bars[hi]:
max_left = max(max_left, bars[lo])
water_total += max_left - bars[lo]
lo += 1
else:
max_right = max(max_right, bars[hi])
water_total += max_right - bars[hi]
hi -= 1
return water_total
The provided Python solution calculates the amount of rainwater trapped between heights represented by an array of integers. The array bars
denotes the height of bars at different positions. The function water_trap
computes the total volume of trapped water utilizing two pointers and a greedy approach:
- Initialize two pointers,
lo
(start) andhi
(end), and set them to the bounds of the array. - Initialize variables to store the maximum height of bars encountered from the left (
max_left
) and the right (max_right
), and a variablewater_total
to accumulate the trapped water. - Use a while loop to iterate until the two pointers meet. Within each iteration:
- Compare the height at the two pointers.
- If the bar on the left (
bars[lo]
) is lower than the bar on the right (bars[hi]
):- Update
max_left
to be the maximum of its current value and the height at locationlo
. - Calculate the trapped water at this position as the difference between
max_left
andbars[lo]
, then incrementlo
.
- Update
- If the bar on the right (
bars[hi]
) is lower or equal:- Similarly, adjust
max_right
, calculate trapped water for the right position, and decrementhi
.
- Similarly, adjust
- Continue this process until all water that can be trapped is accounted for.
- Return
water_total
, which now contains the total amount of trapped rainwater.
This method ensures that you efficiently find water trapped between bars in O(n) time complexity and O(1) space, handling each bar at most once.
No comments yet.