[LeetCode] 2281. Sum of Total Strength of Wizards

As the ruler of a kingdom, you have an army of wizards at your command.

You are given a 0-indexed integer array strength, where strength[i] denotes the strength of the ith wizard. For a contiguous group of wizards (i.e. the wizards' strengths form a subarray of strength), the total strength is defined as the product of the following two values:

  • The strength of the weakest wizard in the group.
  • The total of all the individual strengths of the wizards in the group.

Return the sum of the total strengths of all contiguous groups of wizards. Since the answer may be very large, return it modulo 109 + 7.

A subarray is a contiguous non-empty sequence of elements within an array.

Example 1:

Input: strength = [1,3,1,2]
Output: 44
Explanation: The following are all the contiguous groups of wizards:
- [1] from [1,3,1,2] has a total strength of min([1]) * sum([1]) = 1 * 1 = 1
- [3] from [1,3,1,2] has a total strength of min([3]) * sum([3]) = 3 * 3 = 9
- [1] from [1,3,1,2] has a total strength of min([1]) * sum([1]) = 1 * 1 = 1
- [2] from [1,3,1,2] has a total strength of min([2]) * sum([2]) = 2 * 2 = 4
- [1,3] from [1,3,1,2] has a total strength of min([1,3]) * sum([1,3]) = 1 * 4 = 4
- [3,1] from [1,3,1,2] has a total strength of min([3,1]) * sum([3,1]) = 1 * 4 = 4
- [1,2] from [1,3,1,2] has a total strength of min([1,2]) * sum([1,2]) = 1 * 3 = 3
- [1,3,1] from [1,3,1,2] has a total strength of min([1,3,1]) * sum([1,3,1]) = 1 * 5 = 5
- [3,1,2] from [1,3,1,2] has a total strength of min([3,1,2]) * sum([3,1,2]) = 1 * 6 = 6
- [1,3,1,2] from [1,3,1,2] has a total strength of min([1,3,1,2]) * sum([1,3,1,2]) = 1 * 7 = 7
The sum of all the total strengths is 1 + 9 + 1 + 4 + 4 + 4 + 3 + 5 + 6 + 7 = 44.

Example 2:

Input: strength = [5,4,6]
Output: 213
Explanation: The following are all the contiguous groups of wizards: 
- [5] from [5,4,6] has a total strength of min([5]) * sum([5]) = 5 * 5 = 25
- [4] from [5,4,6] has a total strength of min([4]) * sum([4]) = 4 * 4 = 16
- [6] from [5,4,6] has a total strength of min([6]) * sum([6]) = 6 * 6 = 36
- [5,4] from [5,4,6] has a total strength of min([5,4]) * sum([5,4]) = 4 * 9 = 36
- [4,6] from [5,4,6] has a total strength of min([4,6]) * sum([4,6]) = 4 * 10 = 40
- [5,4,6] from [5,4,6] has a total strength of min([5,4,6]) * sum([5,4,6]) = 4 * 15 = 60
The sum of all the total strengths is 25 + 16 + 36 + 36 + 40 + 60 = 213.

Constraints:

  • 1 <= strength.length <= 105
  • 1 <= strength[i] <= 109

巫师的总力量和。

作为国王的统治者,你有一支巫师军队听你指挥。

给你一个下标从 0 开始的整数数组 strength ,其中 strength[i] 表示第 i 位巫师的力量值。对于连续的一组巫师(也就是这些巫师的力量值是 strength 的 子数组),总力量 定义为以下两个值的 乘积 :

巫师中 最弱 的能力值。
组中所有巫师的个人力量值 之和 。
请你返回 所有 巫师组的 总 力量之和。由于答案可能很大,请将答案对 109 + 7 取余 后返回。

子数组 是一个数组里 非空 连续子序列。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/sum-of-total-strength-of-wizards
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路是单调栈 + 前缀和。可以先做一下907题2104题,思路很像。这一题算是前两题的升华。我参考了这个帖子

注意题目的要求,让我们找的是若干符合题意的子数组。对于任何一个数组而言,找所有子数组的时间复杂度是 O(n!),再加上还要找每个子数组里的最小值,还要再算这个最小值和子数组里所有数字的乘积。

我们可以利用907题的思路,如果当前数字是某个子数组的最小值,那么我们可以用单调栈找到这个子数组的左右边界。知道左右边界之后如何快速知道这一段子数组的和,我们需要用到前缀和的技巧。

时间O(n)

空间O(n)

Java实现

 1 class Solution {
 2     public int totalStrength(int[] strength) {
 3         // corner case
 4         if (strength == null || strength.length == 0) {
 5             return 0;
 6         }
 7 
 8         // normal case
 9         int res = 0;                            // Stores the sum of total strengths of all groups of wizards
10         int MOD = (int) Math.pow(10, 9) + 7;       // Modulus used for the answer
11         int sum = 0;
12         int n = strength.length;                        // Length of input
13 
14         // Init a Monotonic Stack - 
15         // Used ArrayDeque for Stack instead of Stack as ArrayDeque does not require acquiring & releasing thread locks, which is costly in time
16         Deque<Integer> stack = new ArrayDeque<>();
17         // Init an int arr to store accumulations
18         int[] presum = new int[n + 2];
19 
20         // Iterate through all wizards strengths from the input array
21         for (int i = 0; i <= n; i++) {
22             int cur = i < n ? strength[i] : 0;
23             sum = (sum + cur) % MOD;
24             presum[i + 1] = (sum + presum[i]) % MOD;
25             while (!stack.isEmpty() && cur < strength[stack.peek()]) {
26                 // 开始计算以strength[j]为最小值的子数组
27                 int j = stack.pop();
28                 int left = stack.isEmpty() ? -1 : stack.peek();
29                 long leftAcc = left < 0 ? presum[j] : presum[j] - presum[left];
30                 long rightAcc = presum[i] - presum[j];
31                 int leftLength = j - left;
32                 int rightLength = i - j;
33                 res = (int) (res + (rightAcc * leftLength - leftAcc * rightLength) % MOD * strength[j] % MOD) % MOD;
34             }
35             stack.push(i);
36         }
37         // Return the sum of the total strengths of all contiguous groups of qizards in mod(10^9) + 7
38         return (res + MOD) % MOD;
39     }
40 }

 

相关题目

907. Sum of Subarray Minimums

2104. Sum of Subarray Ranges

2281. Sum of Total Strength of Wizards

LeetCode 题目总结

posted @ 2023-01-13 06:40  CNoodle  阅读(109)  评论(0编辑  收藏  举报