1.题目基本信息
1.1.题目描述
如果一个长度为 n 的数组 arr 符合下面其中一个条件,可以称它 连续:
- 对于所有的 1 <= i < n,arri - arri - 1 == 1。
- 对于所有的 1 <= i < n,arri - arri - 1 == -1。
数组的 值 是其元素的和。
例如,3, 4, 5 是一个值为 12 的连续数组,并且 9, 8 是另一个值为 17 的连续数组。而 3, 4, 3 和 8, 6 都不连续。
给定一个整数数组 nums,返回所有 连续 非空 子序列 的 值 之和。
由于答案可能很大,返回它对 109 + 7 取模 的值。
注意 长度为 1 的数组也被认为是连续的。
1.2.题目地址
https://leetcode.cn/problems/sum-of-consecutive-subsequences/description/
2.解题方法
2.1.解题思路
动态规划
时间复杂度:O(n)
2.2.解题步骤
第一步,状态定义。dpupi0表示以i结尾的最长连续递增子序列的长度(也就是能够匹配的数组的数量),dpupi0表示以i结尾的所有连续递增子序列的求和结果。dpdowni0表示以i结尾的最长连续递减子序列的长度(也就是能够匹配的连续递减数组的数量),dpdowni0表示以i结尾的所有连续递减子序列的求和结果。
第二步,状态初始化。dpup*0=0,dpup* 1=0;dpdown*0=0,dpdown*1=0
第三步,状态转移。dpupi0+=dpupi-10+1,dpupi1+=dpupi-11+i*(dpupi-10+1);dpdowni0+=dpdowni+10+1,dpdowni1+=dpdowni+11+i*(dpdowni+10+1)(注:这里使用的是+=的递推符号,因为nums后面可能出现重复的数字)
第四步,最终的sum(dpup)+sum(dpdown)-sum(nums)即为题解(因为up和down都算了一次单元素数组,所以需要减去sum(nums)的部分)
3.解题代码
Python代码
python
class Solution:
def getSum(self, nums: List[int]) -> int:
# 思路:动态规划
m = max(nums)
# 第一步,状态定义。dpup[i][0]表示以i结尾的最长连续递增子序列的长度(也就是能够匹配的数组的数量),dpup[i][0]表示以i结尾的所有连续递增子序列的求和结果。dpdown[i][0]表示以i结尾的最长连续递减子序列的长度(也就是能够匹配的连续递减数组的数量),dpdown[i][0]表示以i结尾的所有连续递减子序列的求和结果。
dpup = [[0, 0] for _ in range(m + 2)]
dpdown = [[0, 0] for _ in range(m + 2)]
# 第二步,状态初始化。dpup[*][0]=0,dpup[*][1]=0;dpdown[*][0]=0,dpdown[*][1]=0
# 第三步,状态转移。dpup[i][0]+=dpup[i-1][0]+1,dpup[i][1]+=dpup[i-1][1]+i*(dpup[i-1][0]+1);dpdown[i][0]+=dpdown[i+1][0]+1,dpdown[i][1]+=dpdown[i+1][1]+i*(dpdown[i+1][0]+1)(注:这里使用的是+=的递推符号,因为nums后面可能出现重复的数字)
for i in nums:
dpup[i][0] += dpup[i - 1][0] + 1
dpup[i][1] += dpup[i - 1][1] + i * (dpup[i - 1][0] + 1)
dpdown[i][0] += dpdown[i + 1][0] + 1
dpdown[i][1] += dpdown[i + 1][1] + i * (dpdown[i + 1][0] + 1)
# 第四步,最终的sum(dpup)+sum(dpdown)-sum(nums)即为题解(因为up和down都算了一次单元素数组,所以需要减去sum(nums)的部分)
mod = 10 ** 9 + 7
result = (sum([dpup[i][1] + dpdown[i][1] for i in range(m + 1)]) - sum(nums)) % mod
return int(result)
4.执行结果
