Skip to content

Latest commit

 

History

History
149 lines (122 loc) · 6.32 KB

README.md

File metadata and controls

149 lines (122 loc) · 6.32 KB

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.

 

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

Companies:
Amazon, Facebook, Goldman Sachs, Bloomberg, Microsoft, Google, Apple, Adobe, Intel, Rubrik, Uber, Citadel, Snapchat, VMware, Qualtrics, Paypal, Tesla, Zoho, Intuit, Oracle

Related Topics:
Array, Two Pointers, Dynamic Programming, Stack, Monotonic Stack

Similar Questions:

Solution 1.

The water that can be held at position i is max(0, min(left[i], right[i]) - A[i]) where left[i] is the maximum height to the left of i and right[i] is the maximum height to the right of i.

// OJ: https://leetcode.com/problems/trapping-rain-water/
// Author: github.com/lzl124631x
// Time: O(N)
// Space: O(N)
class Solution {
public:
    int trap(vector<int>& A) {
        int N = A.size(), ans = 0;
        vector<int> left(N, 0), right(N, 0);
        for (int i = 1; i < N; ++i) left[i] = max(left[i - 1], A[i - 1]);
        for (int i = N - 2; i >= 0; --i) right[i] = max(right[i + 1], A[i + 1]);
        for (int i = 1; i < N - 1; ++i) ans += max(0, min(left[i], right[i]) - A[i]);
        return ans;
    }
};

Or compute left on the fly.

// OJ: https://leetcode.com/problems/trapping-rain-water/
// Author: github.com/lzl124631x
// Time: O(N)
// Space: O(N)
class Solution {
public:
    int trap(vector<int>& A) {
        int N = A.size(), ans = 0, left = 0;
        vector<int> right(N);
        for (int i = N - 2; i >= 0; --i) right[i] = max(right[i + 1], A[i + 1]);
        for (int i = 0; i < N; ++i) {
            ans += max(0, min(left, right[i]) - A[i]);
            left = max(left, A[i]);
        }
        return ans;
    }
};

Solution 2. Monotonic stack

This solution is similar to the Monotonic Stack solution to 84. Largest Rectangle in Histogram (Hard).

The intuition is that once we see a taller A[i], all A[j] <= A[i] (j < i) are no longer relevant because we will at most use A[i] as the left edge.

So, we maintain a monotonic stack s storing the relevant indices.

For each A[i], we pop indices <= A[i] from s. For each popped index mid, the index triple s.top(), mid, i forms a rectangle of water. The width is i - s.top() - 1, the height is min(A[s.top()], A[i]) - A[mid].

// OJ: https://leetcode.com/problems/trapping-rain-water/
// Author: github.com/lzl124631x
// Time: O(N)
// Space: O(N)
class Solution {
public:
    int trap(vector<int>& A) {
        int N = A.size(), ans = 0;
        stack<int> s;
        for (int i = 0; i < N; ++i) {
            while (s.size() && A[i] >= A[s.top()]) {
                int mid = s.top();
                s.pop();
                if (s.size()) ans += (i - s.top() - 1) * (min(A[i], A[s.top()]) - A[mid]);
            }
            s.push(i);
        }
        return ans;
    }
};

Solution 3. Two Pointers

Can we save the O(N) space in solution 1? The space is taken by the right array storing the maximum heights. We can try using a single pointer instead.

Let's traverse i from 0 rightwards. For each A[i], instead of using right[i] -- the tallest height to the right of A[i], we use a pointer j = N-1. As long as A[j] >= A[i], the height of the water filled at index i is determined only by left -- left - A[i].

So, we keep incrementing i and fill left - A[i] at index i, until A[i] > A[j].

Now, the setup is reversed. Due to symmetry, now we should keep decrementing j and fill right - A[j] at index j, until A[j] >= A[i].

// OJ: https://leetcode.com/problems/trapping-rain-water/
// Author: github.com/lzl124631x
// Time: O(N)
// Space: O(1)
class Solution {
public:
    int trap(vector<int>& A) {
        int i = 0, j = A.size() - 1, left = 0, right = 0, ans = 0;
        while (i < j) {
            if (A[i] < A[j]) {
                left = max(left, A[i]);
                ans += left - A[i++];
            } else {
                right = max(right, A[j]);
                ans += right - A[j--];
            }
        }
        return ans;
    }
};