package pers.mao.stackAndQueue.demo_11;
import java.util.Stack;
/**
* @author Mao Qingbo
* @date 2021-01-27
*/
public class GetVisibleMountainNum {
public int getVisibleNum(int [] arr){
if(arr == null || arr.length < 2){
return 0;
}
int size = arr.length;
int maxIndex = 0;
//先在环中找到其中一个最大值的位置,哪一个都行
for(int i = 0; i < size; i++){
maxIndex = arr[maxIndex] < arr[i] ? i : maxIndex;
}
Stack<Record> stack = new Stack<Record>();
//先将(最大值,1)这个记录放在stack中
stack.push(new Record(arr[maxIndex]));
//从最大值位置的下一个位置开始沿next方向遍历
int index = nextIndex(maxIndex,size);
//用“小找大”的方式统计所有可见山峰对
int res = 0;
//遍历开始,当index再次回到maxIndex的时候,说明转了一圈,遍历结束
while(index != maxIndex){
//当前数字arr[index]要进站,判断是否能满足栈顶到栈底依次递增
//若能,则压入栈;若不能,则弹出栈顶记录,并计算山峰对数量
while(stack.peek().value < arr[index]){
int k = stack.pop().times;
//弹出记录为(x,k),如果k == 1,产生两对;如果k > 1,产生 2*k+C(2,k)对
res += getInternalSum(k) + 2 * k;
}
//当前数字arr[index]要进栈,若和栈顶数字一样,就合并;否则将记录(arr[index],1)压入栈
if(stack.peek().value == arr[index]){
stack.peek().times++;
}
else{
stack.push(new Record(arr[index]));
}
index = nextIndex(index,size);
}
//清算阶段开始
//清算阶段的第1小阶段
while (stack.size() > 2){
int times = stack.pop().times;
res += getInternalSum(times) + 2 * times;
}
//清算阶段的第2小阶段
if(stack.size() == 2){
int times = stack.pop().times;
res += getInternalSum(times) + times;
}
//清算阶段的第3小阶段
res += getInternalSum(stack.pop().times);
return res;
}
//环形数组当前位置为i,数组长度为size,返回i的下一个位置
public int nextIndex(int i,int size){
return i < size -1 ? i+1 : 0;
}
//如果k == 1,返回0;否则,返回C(2,k)
public int getInternalSum(int k){
return k == 1 ? 0 : (k * (k - 1) / 2);
}
}
可见的山峰对数量
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 在常见的业务场景中经常会遇到分类统计的问题,如下表所示学生分数,需求: 1.取得不同分数段学生的绝对数量(优良中差...