413. Arithmetic Slices -Medium

本文介绍了一种高效算法来计算数组中等差数列的数量,通过两种方法实现:一种是直接计算等差数列长度并使用数学公式得出结果;另一种是采用动态规划方法,递推计算等差数列的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Question

A sequence of number is called arithmetic if it consists of at least three elements and if the difference between any two consecutive elements is the same.

For example, these are arithmetic sequence:

1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9

The following sequence is not arithmetic.

1, 1, 2, 5, 7

A zero-indexed array A consisting of N numbers is given. A slice of that array is any pair of integers (P, Q) such that 0 <= P < Q < N.

A slice (P, Q) of array A is called arithmetic if the sequence:
A[P], A[p + 1], …, A[Q - 1], A[Q] is arithmetic. In particular, this means that P + 1 < Q.

The function should return the number of arithmetic slices in the array A.

如果一个数组是由至少3个元素组成,且任意两个连续元素之差都相等,那么我们称它为等差数列。现在给定一个包含N个元素的数组,要求找出该数组中有多少个等差数列

Example

A = [1, 2, 3, 4]

return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] itself.

Solution

  • 第一种方法我们可以找出等差数列长度和其中包含的等差数列个数的关系,假设等差数列长度为n,那么等差数列个数为:(n - 1) * (n - 2) / 2。也就是如果我们得到每一个最长等差数列,那么代入公式即可得到该等差数列包含的等差数列个数

    class Solution(object):
        def numberOfArithmeticSlices(self, A):
            """
            :type A: List[int]
            :rtype: int
            """
            res = 0
            len_consecutive_elements = 2
            for index in range(2, len(A)):
                # 如果该元素属于等差数列,那么等差数列长度+1
                if A[index] - A[index - 1] == A[index - 1] - A[index - 2]:
                    len_consecutive_elements += 1
                # 如果该元素不属于等差数列,带入公式计算包含等差数列个数,重置len
                else:
                    if len_consecutive_elements >= 3:
                        res += int((len_consecutive_elements - 1) * (len_consecutive_elements - 2) / 2)
                    len_consecutive_elements = 2
            # 带入公式计算最后一个等差数列
            res += int((len_consecutive_elements - 1) * (len_consecutive_elements - 2) / 2)
            return res
  • 第二种更快的方法是动态规划。假设我们需要得到[1, 2, 3, 4, 5]的等差数列个数,如果我们能得到它与[1, 2, 3, 4]之间的递推式,那么就很好的解决这个问题了,而事实上它确实是有迹可循的。假设dp[i]为列表前i个数的等差数列个数,递推式为:d[i] = d[i - 1] + j,而j是一个可变量,它的规律如下表

    列表等差数列个数j
    [1, 2, 3]11
    [1, 2, 3, 4]32
    [1, 2, 3, 4, 5]63
    [1, 2, 3, 4, 5, 6]104

    所以我们在遍历的过程中保存下j即可,代码如下

    class Solution(object):
    def numberOfArithmeticSlices(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        if len(A) == 0: return 0
        i = 1
        dp = [0] * len(A)
        for index in range(2, len(A)):
            # 如果属于等差数列则带入递推式,注意更新i(原公式j)
            if A[index] - A[index - 1] == A[index - 1] - A[index - 2]:
                dp[index] = dp[index - 1] + i
                i += 1
            # 如果不属于等差数列则代表等差数列个数不发生改变,同时重置i
            else:
                dp[index] = dp[index - 1]
                i = 1
        return dp[-1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值