单调栈
- 单调栈介绍
- 求最大矩阵的大小
- 烽火台
单调栈介绍:
-
若是单调递增栈,则从栈顶到栈底的元素是严格递增的。若是单调递减栈,则从栈顶到栈底的元素是严格递减的。
-
越靠近栈顶的元素越后进栈。
-
想要解决的问题的获取左边离它最近的比它大(小)的和右边离它最近的比它大(小)的。
求最大矩阵的大小
public static int maxRecSize(int[][] map) {
if (map == null || map.length == 0 || map[0].length == 0) {
return 0;
}
int maxArea = 0;
int[] height = new int[map[0].length];
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
height[j] = map[i][j] == 0 ? 0 : height[j] + 1;
}
maxArea = Math.max(maxArea, maxRecFromBottom(height));
}
return maxArea;
}
private static int maxRecFromBottom(int[] height) {
if (height == null || height.length == 0) {
return 0;
}
int maxArea = 0;
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < height.length; i++) {
while (!stack.isEmpty() && height[i] <= height[stack.peek()]) {
int j = stack.pop();
int k = stack.isEmpty() ? -1 : stack.peek();
maxArea = Math.max((i - k - 1) * height[j], maxArea);
}
stack.push(i);
}
while (!stack.isEmpty()) {
int j = stack.pop();
int k = stack.isEmpty() ? -1 : stack.peek();
maxArea = Math.max((height.length - k - 1) * height[j], maxArea);
}
return maxArea;
}
3. 烽火台
给一个数组,代表环形的山
-
每座山上会放烽火,相邻可看见烽火
-
不相邻的山峰,两条路中其中一条路上的烽火都不大于他们之间的最小值,就能看见
返回能相互看见的山峰有多少对?
public static long communications(int[] arr) {
if (arr == null || arr.length == 0) {
return 0L;
}
int maxIndex = 0;
int size = arr.length;
for (int i = 0; i < size; i++) {
maxIndex = arr[maxIndex] > arr[i] ? maxIndex : i;
}
int value = arr[maxIndex];
Stack<Pair> stack = new Stack<>();
stack.push(new Pair(value));
int index = nextIndex(size, maxIndex);
long res = 0;
while (index != maxIndex) {
value = arr[index];
while (!stack.isEmpty() && stack.peek().value < value) {
int times = stack.pop().times;
res += getInternalSum(times) + 2 * times;
}
if (!stack.isEmpty() && stack.peek().value == value) {
stack.peek().times++;
} else {
stack.push(new Pair(value));
}
index = nextIndex(size, index);
}
while (!stack.isEmpty()) {
int times = stack.pop().times;
res += getInternalSum(times);
if (!stack.isEmpty()) {
res += times;
if (stack.size() > 1) {
res += times;
} else {
res += stack.peek().times > 1 ? times : 0;
}
}
}
return res;
}
private static long getInternalSum(int n) {
return n == 1L ? 0L : (long) n * (long) (n - 1) / 2L;
}
private static int nextIndex(int size, int i) {
return i < (size - 1) ? (i + 1) : 0;
}
private static class Pair {
public int value;
public int times;
public Pair(int value) {
this.value = value;
this.times = 1;
}
}