- 接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
思路:每次给一个方法提供数组的一部分,算这部分数组的“0”号位置的柱子向右可以容纳的雨水
考虑两种情况
1.
这种情况,如果正常计算的话,会多计算一部分,
(红色部分是应该计算的部分,黑色部分是多计算的部分)
解决方案:
倒序重新计算,取两次最小值
2.
和第一种情况类似,但是会有点不同,那就是中间会有个凸起(即除了首元素外的最大值),将凸起点的雨水值和点记住,
Ps:不能有一个凸点就直接退出循环,因为不知道这个凸点是不是全局的凸点。
然后从凸点重新向前遍历
重点
其实最重要的就是将最后保留下的序列值赋给循环中的 变量 i
其实有一个小情况,就不单独当一个重点说,那就是剩下的数组长度为2(或更小)的时候,直接返回到数组末尾就可以了,因为不可能在有雨水可以存下
本人正解
class Solution {
public int trap(int[] height) {
int quantity = 0;
for (int i = 0; i < height.length; ) {
int[] temp = new int[height.length - i];
System.arraycopy(height, i, temp, 0, height.length - i);
int[] trap = findTrap(temp);
quantity += trap[0];
i += trap[1];
}
return quantity;
}
public int[] findTrap(int[] height) {
if (height.length<=2) {
return new int[]{0, height.length };
}
int quantity1 = 0;
int quantity2 = Integer.MAX_VALUE;
int index = 1;
int[] max = {0, 1};
for (int i = 1; i < height.length; i++) {
if (height[i] < height[0]) {
quantity1 = quantity1 + height[0] - height[i];
}
if (height[i] >= height[max[1]]) {
max = new int[]{quantity1, i};
}
if (height[i] >= height[0]||i==height.length-1) {
index = max[1];
quantity1 = max[0];
break;
}
}
if (height[0]>height[max[1]]) {
quantity2 = 0;
int temp = index;
for (int i = temp - 1; i >= 0; i--) {
if (height[i] < height[temp]) {
quantity2 = quantity2 + height[temp] - height[i];
}
if (quantity2 == 0) {
temp--;
}
}
}
return new int[]{Math.min(quantity1, quantity2),index};
}
}
代码分析
时间复杂度:
最好 O(n)
最坏 O(n^2)