https://leetcode.cn/problems/trapping-rain-water/description/
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
这道题如果难的话就是难在思路,怎么去算
三、终版 o(n)
找到最高点,两边依次以最高边为终边,看自己是否有积水,是否有积水取决于历史是否有高过自己的点,积水多少取决于历史最高点-当前高度
public int trap(int[] height) {
if (height.length < 2) {
return 0;
}
int maxIdx = 0;
for (int i = 1; i < height.length; i++) {
if (height[i] > height[maxIdx]) {
maxIdx = i;
}
}
int totalCnt = 0;
int nearMaxH = height[0];
for (int i = 1; i < maxIdx; i++) {
if (height[i] > nearMaxH) {
nearMaxH = height[i];
}
totalCnt += nearMaxH - height[i];
}
nearMaxH = height[height.length - 1];
for (int i = height.length - 2; i > maxIdx; i--) {
if (height[i] > nearMaxH) {
nearMaxH = height[i];
}
totalCnt += nearMaxH - height[i];
}
return totalCnt;
}
二、排序版 o(nlogn)
先排序->为了找最高点
定位两个最高点a,b;次高点依次去算 与 最近高点a/b 之间 累计的雨量;并更新a/b
public int trap(int[] height) {
if (height.length < 2) {
return 0;
}
List<Integer> idxList = IntStream.range(0, height.length).boxed()
.sorted(Comparator.comparing((Integer idx) -> height[idx]).reversed()).collect(Collectors.toList());
int left = Math.min(idxList.get(0), idxList.get(1));
int right = Math.max(idxList.get(0), idxList.get(1));
int totalCnt = findHeight(left, right, height, height[idxList.get(1)]);
for (int i = 2; i < idxList.size(); i++) {
int idx = idxList.get(i);
if (idx < left) {
totalCnt += findHeight(idx, left, height, height[idx]);
left = idx;
} else if (idx > right) {
totalCnt += findHeight(right, idx, height, height[idx]);
right = idx;
} else {
// do nothing
}
if (left == 0 && right == height.length) {
break;
}
}
return totalCnt;
}
private int findHeight(int left, int right, int[] height, int top) {
return IntStream.range(left + 1, right).map(idx -> height[idx]).map(h -> top - h).filter(h -> h > 0).sum();
}
一、枚举版 n^2(未通过时间限制)
按高度、从左到右依次枚举累加,即o(h*n)
小优化:在累加过程中剔除不满足条件的n,然并r,依旧超时不通过
public int trap(int[] height) {
int cmpHeight = 1;
int totalCnt = 0;
int roundMatchCnt = 0;
List<Integer> validIdxList = IntStream.range(0, height.length).boxed().collect(Collectors.toList());
do {
int lastIdx = -1;
int cnt = 0;
roundMatchCnt = 0;
Iterator<Integer> iter = validIdxList.iterator();
while (iter.hasNext()) {
int i = iter.next();
if (height[i] >= cmpHeight) {
if (lastIdx >= 0 && i - lastIdx > 1) {
cnt += (i - lastIdx - 1);
}
lastIdx = i;
roundMatchCnt++;
} else {
iter.remove();
}
}
totalCnt += cnt;
cmpHeight++;
} while (roundMatchCnt >= 2);
return totalCnt;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。