413. 等差数列划分

方法一:暴力

class Solution:
    def numberOfArithmeticSlices(self, nums: List[int]) -> int:
        def isArithmeticProgression(x):
            n = len(x)
            # if n < 3:return False
            d = x[1] - x[0]
            for i in range(2, n):
                if x[i] - x[i-1] != d: return False
            return True

        res, n = 0, len(nums)
        if n < 3:return 0
        for i in range(n):
            for j in range(i + 2, n):
                if isArithmeticProgression(nums[i:j+1]): res += 1
                else: break

        return res

方法二:双指针(滑动窗口)

class Solution:
    def numberOfArithmeticSlices(self, nums: List[int]) -> int:
        n, res = len(nums), 0
        # if n < 3: return 0 
        for i in range(1,n):
            d = nums[i] - nums[i - 1]
            for j in range(i + 1, n):
                if nums[j] - nums[j - 1] == d: res += 1
                else: break
     
        return res

方法三:动态规划

定义 dp[i] 是以 nums[i] 为终点的等差数列的个数。
初始状态:dp[0] = 0
转移方程:
413. 等差数列划分_双指针

返回:sum(dp)

class Solution:
    def numberOfArithmeticSlices(self, nums: List[int]) -> int:
        n = len(nums)
        dp = [0] * n
        
        for i in range(2, n):
            if nums[i - 2] + nums[i] == nums[i - 1] * 2:
                dp[i] = dp[i - 1] + 1
                
        return sum(dp)

由于 dp[i] 只和 dp[i - 1] 有关,所以可以进行状态压缩,只用一个变量 k 来表示以 nums[i] 为终点的等差数列的个数。

方法四:简化

cclass Solution:
    def numberOfArithmeticSlices(self, nums: List[int]) -> int:
        n, k, res = len(nums), 0, 0  

        for i in range(2, n):
            if nums[i] + nums[i - 2] == 2 * nums[i - 1]: 
	            k += 1
	            res += k
            else: 
            	k = 0            
        
        return res