题目
思路
动态规划
每一个位置能够达到的最大高度等于两边最大高度的最小值,则可以通过动态规划得到每个位置两边的最大值,然后求得结果。
单调栈
将每个pos依次进栈,当待进栈元素大于栈顶元素并且栈不为空是时,出栈并计算当前情况的得到的雨水值。
双指针
设置left_max和right_max,left和right,如果left_max大的话,移动right,每步移动计算每步雨水值;反之left移动,同样每步移动计算每步的雨水值。
实现
动态规划
class Solution {
public:
int trap(vector<int>& height) {
int len = height.size();
vector<int> left_max(len);
vector<int> right_max(len);
left_max[0] = height[0];
for (int i = 1; i < len - 1; ++i)
left_max[i] = max(left_max[i - 1], height[i]);;
right_max[len - 1] = height[len - 1];
for (int i = len - 2; i > 0; --i)
right_max[i] = max(right_max[i + 1], height[i]);
int ret = 0;
for (int i = 1; i < len - 1; ++i)
ret += min(left_max[i], right_max[i]) > height[i] ? min(left_max[i], right_max[i]) - height[i] : 0;
return ret;
}
};
单调栈
class Solution {
public:
int trap(vector<int>& height) {
int ret = 0;
stack<int> stk;
int n = height.size();
for (int i = 0; i < n; ++i) {
while (!stk.empty() && height[stk.top()] < height[i]) {
int top = stk.top();
stk.pop();
if (stk.empty())
break;
int left = stk.top();
int cur_width = i - left - 1;
int cur_height = min(height[left], height[i]) - height[top];
ret += cur_height * cur_width;
}
stk.emplace(i);
}
return ret;
}
};
双指针
class Solution {
public:
int trap(vector<int>& height) {
int len = height.size();
int left_max = height[0];
int right_max = height[len - 1];
int left = 0;
int right = len - 1;
int ret = 0;
while (left < right) {
if (left_max > right_max) {
ret += right_max - height[right];
right--;
right_max = max(right_max, height[right]);
}
else {
ret += left_max - height[left];
left++;
left_max = max(left_max, height[left]);
}
}
return ret;
}
};
接雨水II
思路
最小堆
将边界位置输入到优先队列,设置visited数组,每次弹出,遍历其周围四个位置,若新位置未遍历过,将设置为max(高度,中心位置高度)并将其入栈,循环直到栈空(所有位置遍历完成)
BFS
设置高度数组,初始化为全局最高高度;将边界位置输入到队列,修改高度数组中高度为位置高度。每次出栈,遍历其上下左右四个位置,若位置上数组高度大于中心位置的高度,将其位置入栈,循环直到栈空。
实现
最小堆
class Solution {
public:
int trapRainWater(vector<vector<int>>& heightMap) {
int result = 0;
int m = heightMap.size();
int n = heightMap[0].size();
if (m <= 2 || n <= 2)
return result;
typedef pair<int, int> pii;
priority_queue<pii, vector<pii>, greater<pii>> q;
vector<vector<bool>> visit(m, vector<bool>(n, false));
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
if (i == 0 || i == m - 1 || j == 0 || j == n - 1) {
visit[i][j] = true;
q.push({ heightMap[i][j], i * n + j });
}
int dict[5] = { -1, 0, 1, 0, -1};
while (!q.empty()) {
pii temp = q.top();
q.pop();
for (int i = 0; i < 4; ++i) {
int poi_i = temp.second / n + dict[i];
int poi_j = temp.second % n + dict[i + 1];
if (poi_i < 0 || poi_j < 0 || poi_i >= m || poi_j >= n || visit[poi_i][poi_j])
continue;
if (temp.first > heightMap[poi_i][poi_j])
result += temp.first - heightMap[poi_i][poi_j];
q.push({ max(temp.first, heightMap[poi_i][poi_j]), poi_i * n + poi_j });
visit[poi_i][poi_j] = true;
}
}
return result;
}
};
BFS
class Solution {
public:
int trapRainWater(vector<vector<int>>& heightMap) {
int m = heightMap.size(), n = heightMap[0].size();
int maxHeight = 0;
int dirs[] = { -1, 0, 1, 0, -1 };
for (int i = 0; i < m; ++i)
maxHeight = max(maxHeight, *max_element(heightMap[i].begin(), heightMap[i].end()));
vector<vector<int>> water(m, vector<int>(n, maxHeight));
queue<pair<int, int>> q;
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
if (i == 0 || i == m - 1 || j == 0 || j == n - 1) {
if (water[i][j] > heightMap[i][j]) {
water[i][j] = heightMap[i][j];
q.push(make_pair(i, j));
}
}
while (!q.empty()) {
int x = q.front().first, y = q.front().second;
q.pop();
for (int i = 0; i < 4; ++i) {
int nx = x + dirs[i], ny = y + dirs[i + 1];
if (nx < 0 || nx >= m || ny < 0 || ny >= n) {
continue;
}
if (water[x][y] < water[nx][ny] && water[nx][ny] > heightMap[nx][ny]) {
water[nx][ny] = max(water[x][y], heightMap[nx][ny]);
q.push(make_pair(nx, ny));
}
}
}
int res = 0;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
res += water[i][j] - heightMap[i][j];
}
}
return res;
}
};