-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWaterBar.java
103 lines (83 loc) · 3.18 KB
/
WaterBar.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package org.sean.array;
import java.util.ArrayDeque;
import java.util.Deque;
// 42. Trapping Rain Water
public class WaterBar {
public int trap(int[] height) {
if (height == null || height.length <= 1) return 0;
int max = 0;
int maxWaterUnit = 0;
Deque<Integer> stack = new ArrayDeque<>();
int i = 0;
while (i < height.length) {
int n = height[i];
if (stack.isEmpty() || height[stack.peek()] >= n) {
stack.push(i);
} else {
int top = stack.pop();
// https://leetcode.com/problems/trapping-rain-water/discuss/17414/A-stack-based-solution-for-reference-inspired-by-Histogram
// Optimization:
// "use a stack that store the indices with decreasing bar height, once we find a bar who's height is
// larger, then let the top of the stack be bot, the cur bar is ir, and the previous bar is il."
maxWaterUnit = stack.isEmpty() ? 0 : (Math.min(height[stack.peek()], n) - height[top]) * (i - stack.peek() - 1);
max += maxWaterUnit;
i--;
}
i++;
}
return max;
}
public int trap0(int[] height) {
if (height == null || height.length <= 1) return 0;
int sum = 0, i = 0;
int len = height.length;
// Stack<Integer> stack = new Stack<>();
// Deque is preferred.
Deque<Integer> stack = new ArrayDeque<Integer>();
int inStackMax = 0;
int inMaxIndex = 0;
while (height[i] <= 0) i++;
while (i < len) {
int h = height[i];
if (stack.isEmpty() || height[stack.peek()] >= h) {
if (h > inStackMax) {
inStackMax = h;
inMaxIndex = i;
}
stack.push(i);
//System.out.println(String.format(">>> Pushed pos: %d, val : %d", i, height[i]));
} else { // h > s[top]
int poppedCnt = 0;
int completionIndex = i;
int boardValue;
while (!stack.isEmpty() && height[stack.peek()] < h) {
if (stack.peek() == inMaxIndex) break;
poppedCnt++;
int top = stack.pop();
int elem = height[top];
boardValue = h;
if (inStackMax < h) {
completionIndex = inMaxIndex;
boardValue = inStackMax;
}
// Math.min(inStackMax, h)
int trappedBlocks = boardValue - elem; // within the boarder
sum += trappedBlocks;
}
// rePush the completed sections
while (poppedCnt > 0) {
stack.push(completionIndex);
poppedCnt--;
}
// rePush current section
stack.push(i);
if (h > inStackMax) {
inStackMax = h;
inMaxIndex = i;
}
}
i++;
}
return sum;
}
}