题目描述
给定一个数组序列,要求选出一个区间。使得该区间是所有区间中经过如下计算之后得出的值最大的一个:
计算规则:区间中最小的数✖️区间所有数的和
最程序输出经过计算的最大值即可,不需要输出具体的区间
如给定序列 [6,2,1] 经过计算后的最大值为:36
解题思路-java
两个关键点是 区间中最小的数、区间所有数的和。单个元素可以被认为是一个区间。然后就是在找到区间中最小的数的同时,如何
计算其区间和。
public int getMax(int[] numbers) {
if(numbers == null || numbers.length == 0) {
return -1;
}
// 定义一个最大值
int max = 0;
int len = numbers.length;
// 定义一个数组用来维护区间和,数组的默认值是0
int[] sum = new int[len+1];
// 计算出区间和
for(int i = 1;i < len;i++) {
sum[i] = numbers[i-1]+sum[i-1];
}
// 利用单调栈解法解决问题
Stack<Integer> stack = new Stack<>();
for(int i = 0;i < len;i++) {
// 如果栈为空 或者 当前值大于等于栈中元素
if(stack.isEmpty() || numbers[i] >= numbers[stack.peek()]) {
// 把 数组下标存入栈中 存入数组下标方便计算区间和
stack.push(i);
} else {
// 如果栈不为空 并且 当前元素小于等于栈中元素,开始进行计算
while(!stack.isEmpty() && numbers[i] <= numbers[stack.peek()]) {
// 开始对栈中元素进行计算
int pop = stack.pop();
// 寻找左边界,右边界为 当前 i...这里+1是因为栈中如果不为空,肯定是比所计算的元素更小的值
int left = stack.isEmpty()?0:(stack.peek()+1);
max = Math.max(max, numbers[pop]*(sum[i] - sum[left]));
}
// 计算完毕,把元素推入栈中
stack.push(i);
}
}
// 计算完毕之后,若栈不为空
while(!stack.isEmpty()) {
int pop = stack.pop();
int left = stack.isEmpty()?0:(stack.peek()+1);
max = Math.max(max, numbers[pop]*(sum[len] - sum[left]));
}
return max;
}
- 测试结果