巫师的总力量和
难度:
标签:
题目描述
代码结果
运行时间: 334 ms, 内存: 34.2 MB
/*
* 思路:
* 利用Java Stream API来处理数组。通过流的方式生成所有可能的子数组,并计算每个子数组的最小值和总和,
* 然后将它们的乘积加到总力量值中。为了防止结果溢出,需要对结果取模。
*/
import java.util.*;
import java.util.stream.IntStream;
public class WizardStrengthStream {
public static int totalStrength(int[] strength) {
int MOD = 1000000007;
long total = IntStream.range(0, strength.length)
.mapToLong(i -> IntStream.range(i, strength.length)
.mapToObj(j -> Arrays.stream(Arrays.copyOfRange(strength, i, j + 1)))
.flatMapToLong(subArray -> {
int minStrength = subArray.min().orElse(0);
long sum = subArray.sum();
return LongStream.of((long) minStrength * sum);
})
.sum())
.reduce(0L, (a, b) -> (a + b) % MOD);
return (int) total;
}
public static void main(String[] args) {
int[] strength1 = {1, 3, 1, 2};
int[] strength2 = {5, 4, 6};
System.out.println(totalStrength(strength1)); // 44
System.out.println(totalStrength(strength2)); // 213
}
}
解释
方法:
此题解使用了单调栈来寻找每个元素在数组中作为最小值能扩展到的最远左右边界。首先,通过遍历数组使用单调栈计算每个元素的左右边界,其中左边界表示当前元素左侧第一个比它小的元素的位置,右边界表示当前元素右侧第一个比它小的元素的位置。此外,使用前缀和技术来快速计算任意子数组的和,避免重复计算带来的性能损失。最后,结合前缀和和左右边界,快速计算出每个元素作为最小值时,所有包含它的子数组的总力量值的和,并累加起来得到最终结果。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么单调栈在这道题中是有效的?它如何帮助确定每个元素的左右边界?
▷🦆
在计算左右边界时,为什么我们在找到一个更小的元素时就停止并设置边界?这样做的原因是什么?
▷🦆
前缀和数组ss是如何构建的,为什么它需要使用两次accumulate函数?
▷🦆
在解法中,计算每个元素作为最小值时的子数组总力量和的公式是怎样的?具体的数学逻辑是什么?
▷