2281.sum-of-total-strength-of-wizards
题目地址(2281. 巫师的总力量和)
https://leetcode.cn/problems/sum-of-total-strength-of-wizards/
题目描述
前置知识
公司
暂无
思路
如果想做出来这道题,建议先做一下简化版的这道题:907. 子数组的最小值之和
简单说一下上面那个简化版的题目。
一种思考方式是计算每一个数组项 nums[i] 对结果的贡献 c[i],那么答案就是对 c[i] 求和。
nums[i] 对结果的贡献是包含 nums[i] 的子数组,且该子数组的最小值是 nums[i]。于是,我们可以分别找到 nums[i] 左侧和右侧第一个比 nums[i] 小的值 l 和 r,那么子数组 [L,R] 就是一个符合要求的子数组。其中 L 范围是 [l+1,i] R 范围是 [i,r-1]。
根据笛卡尔积可知,每一项 a 对结果的贡献就是 a * (i - l) * (r - i)
而找到左侧(或者右侧)第一个比其大(或者小)的元素考虑使用单调栈。
参考代码:
对这道题来说,我们也需要知道左侧和右侧第一个比其小的,因此使用单调栈也可以解决。不同的是,我们需要求所有子数组和的和。
和前面一样子数组 [L,R] 就是一个符合要求的子数组。其中 L 范围是 [l+1,i] R 范围是 [i,r-1]。
关键是每一项 a 对结果的贡献是多少呢?我们知道子数组和可以用前缀和来计算,只要知道左右端点即可求出。而这里有两个变量,一个是左边界,一个是右边界。
假设我们符合要求的子数组是 l1,l2,l3,a,r1,r2,r3
不妨固定其中一个,以固定左边界为例。我们先固定 l1, 那么右边界就可以是 r1,r2,r3。此时的贡献是 s[r3] - s[l1](即子 l1 到 r3 这一段的贡献)+ s[r2] - s[l1](即子 l1 到 r2 这一段的贡献)+ s[r1] - s[l1](即子 l1 到 r1 这一段的贡献)。类似的,我们需要固定 l2 和 l3 。 因此一共有 3 个 s[l1],3 就是 a 右侧元素个数 rn。
因此每一项 a 对结果的贡献就是 a * (racc * ln - lacc * rn) % mod
关键点
计算每一项对结果的贡献
固定一个变量
代码
语言支持:Python3
Python3 Code:
复杂度分析
令 n 为数组长度。
时间复杂度:$O(n)$
空间复杂度:$O(n)$
参考
此题解由 力扣刷题插件 自动生成。
力扣的小伙伴可以关注我,这样就会第一时间收到我的动态啦~
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
最后更新于