我反而觉得高级篇会简单一些,毕竟不用算全排列并且将其按字典顺序输出,计算过程虽然比较多,但是整个逻辑还是很清楚的。这里依然用到了单调栈这种数据结构,然后就是入栈和出栈的时候需要计算一下能看到的山峰的个数(需要分类讨论)。
两个辅助函数,一个用来模拟环形结构,一个用来计算组合数。
详细内容还是推荐看书《程序员代码面试指南》,写的非常详细,一看就懂了。
import java.util.Stack;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
class Node {
int val;
int time;
Node(int val) {
this.val = val;
this.time = 1;
}
}
public class Main {
public static int getVisibleTime(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
Stack<Node> stack = new Stack<>();
int maxIndex = 0;
int size = arr.length;
int res = 0;
for (int i = 0; i < size; i++) {
maxIndex = arr[maxIndex] > arr[i] ? maxIndex : i;
}
stack.push(new Node(maxIndex));
int index = nextIndex(maxIndex, size);
while (index != maxIndex) {
while (!stack.isEmpty() && arr[stack.peek().val] < arr[index]) {
int t = stack.pop().time;
res += getInternalSum(t) + 2 * t;
}
if (arr[stack.peek().val] == arr[index]) {
stack.peek().time++;
} else {
stack.push(new Node(index));
}
index = nextIndex(index, size);
}
while (stack.size() > 2) {
int t = stack.pop().time;
res += (getInternalSum(t) + 2 * t);
}
if (stack.size() > 1) {
int t = stack.pop().time;
res += getInternalSum(t) + (stack.peek().time == 1 ? t : 2 * t);
}
res += getInternalSum(stack.pop().time);
return res;
}
public static int nextIndex(int i, int size) {
return i < size - 1 ? i + 1 : 0;
}
public static int getInternalSum(int index) {
return index == 1 ? 0 : (index * (index - 1) / 2);
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
int len = Integer.parseInt(bf.readLine());
int[] arr = new int[len];
String[] elements = bf.readLine().split(" ");
for (int i = 0; i < len; i++) {
arr[i] = Integer.parseInt(elements[i]);
}
System.out.println(getVisibleTime(arr));
}
}