トピックの説明
配列シーケンスが与えられた場合、間隔を選択する必要があります。この間隔は、すべての間隔の中で次の計算の後に得られる最大値を持つものとします。
計算ルール: 区間内の最小の数値 ✖️ 区間内のすべての数値の合計
プログラムは、特定の間隔を出力する代わりに、計算された最大値を出力できます。
たとえば、指定されたシーケンス [6,2,1] の計算された最大値は次のようになります: 36
問題解決のアイデア - Java
重要な 2 つのポイントは、区間内の最小の数値と、区間内のすべての数値の合計です。単一の要素は間隔として考えることができます。次に、区間内の最小の数を見つけながら、次のようにします。
その間隔の合計を計算します。
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;
}
- 試験結果