Leetcode 413. Arithmetic Slices
- 题目
- 解析:一维动态规划
题目
解析:一维动态规划
- 这道题目的dp比较特殊,不同于以往dp[i]的定义,这边的dp[i]代表在i这个位置能够组成的新的arithmetic slices。
- 为什么这么定义呢?因为我们可以发现,对于i这个位置来说,能够组成的新的arithmetic slices比i - 1的位置多一个。也就是dp[i] = dp[i-1]+1。
- 为什么是这样的关系呢?因为当我们现在有了一个新元素A[i]的时候,如果A[i]符合条件的话,意味着之前i - 1位置的arithmetic slices都可以在后面接上A[i-1]形成dp[i-1]个新的slices。除此之外,将A[i]和它前面的两个元素组成的slice也一定在之前没有出现,因为slice的最小长度为3
- 由于dp定义的特殊性,所以最后的结果是dp数组的sum
python代码如下:
class Solution:def numberOfArithmeticSlices(self, A: List[int]) -> int:n = len(A)dp = [0]*nfor i in range(2,n):if A[i]-A[i-1] == A[i-1]-A[i-2]:dp[i] = dp[i-1]+1return sum(dp)
当然这道题目可以进一步做个状态压缩,也就是所谓的constant space dynamic programming。因为dp[i]只与dp[i-1]有关,所以dp数组可以用一个变量来代替。
- 要注意的是,一旦出现的新元素不符合之前的等差,那么当前的dp变量要清0
python代码如下:
class Solution:def numberOfArithmeticSlices(self, A: List[int]) -> int:n = len(A)curr = _sum = 0for i in range(2,n):if A[i]-A[i-1] == A[i-1]-A[i-2]:curr += 1_sum += currelse:curr = 0return _sum
C++代码如下:
- C++用accumulate函数求和,accumulate带有三个形参:头两个形参指定要累加的元素范围,第三个形参则是累加的初值。
class Solution {
public:int numberOfArithmeticSlices(vector<int>& A) {
int n = A.size();vector<int> dp(n,0);for (int i=2;i<n;++i){
if (A[i]-A[i-1] == A[i-1]-A[i-2]){
dp[i] = dp[i-1]+1;}}return accumulate(dp.begin(),dp.end(),0);}
};