leetcode 413. 等差数列划分

413. 等差数列划分

如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。

例如,以下数列为等差数列:

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

以下数列不是等差数列。

1, 1, 2, 5, 7

 

数组 A 包含 N 个数,且索引从0开始。数组 A 的一个子数组划分为数组 (P, Q),P 与 Q 是整数且满足 0<=P<Q<N 。

如果满足以下条件,则称子数组(P, Q)为等差数组:

元素 A[P], A[p + 1], ..., A[Q - 1], A[Q] 是等差的。并且 P + 1 < Q 。

函数要返回数组 A 中所有为等差数组的子数组个数。

 

示例:

A = [1, 2, 3, 4]

返回: 3, A 中有三个子等差数组: [1, 2, 3], [2, 3, 4] 以及自身 [1, 2, 3, 4]。

在leetcode刷题时顺带在代码里写上了思路,但是只是随手的草笔

现在来博客随便写一下思路

首先,题目要求的是,查找连续的等差数列,前提要求是下标连续,介于LeetCode经常下坑在小细节,比如说这里要求等差数列,等差数列至少要有3个数,但是传入的数据有可能会是空串,也可能会是只有2个数,因此需要对这个先进行特殊处理

其次,从题目中看到,查找的是下标连续的为等差数组的子数组,从题目中的样例可以看出

[1,2,3,4]可以拆分成[1,2,3,4],[1,2,3],[2,3,4]

那么按照这个推算,假如数据为[1,2,3,4,5],那么拆分应该为,[1,2,3,4,5],[1,2,3,4],[2,3,4,5],[1,2,3],[2,3,4],[3,4,5]

可以看出,长度为n的等差数列数组的拆分可以看成,以n为窗口大小进行一次滑动,滑动到数组的最后,查看能滑动几次,【也就是一次】,然后以n-1为窗口大小进行第二次滑动,同上【也就是二次】,循环这个步骤,直到窗口大小为3的时候,进行完这次窗口遍历后,停止。【这个方法可以统计出一个长度为n的等差数列所能拆分的数目,但是效率不怎么好】

在上面这个推算中,可以找到规律,长度为n的等差数列,在第一次,窗口大小为n的时候,能滑动的次数是1,第二次,窗口大小为n-1的时候,能滑动的次数是2,第三次是3......最后一次是n-3。从上规律可以得出,长度为n的等差数列,可以分成的子数组数目为,1+2+3+....+(n-3),粗暴一点的方法就是,找到一个等差数列,得到最长长度,用for遍历一次,得出结果。优化一点的方法是用等差数列求和公式

 

从上述已经可以知道,得出一个等差数列,如何能分割的字数组长度了

接下来要解决的是,如何查找所给的数组中,各个最长的等差数列长度【要注意一点,题目可能会出现的是[1,2,3,4,5,8,9,10,11],这种数组,里面可以分成两个最长的等差数列,分别为[1,2,3,4,5],[8,9,10,11],这样这个数组的最大值就是[1,2,3,4,5]能拆分出的子数组+[8,9,10,11]能拆分出的子数组】

我用的方法是,存储两个值,第一个值是等差数列中的第二个数减第一个数的大小,命名为cha1,第二个值是第三个数减第二个数的大小,命名为cha2,每一次向后推一位,将cha2赋值给cha1,然后把后一位数的值减去之前的第三个数的值,将结果赋值给cha2,如果cha2不等于cha1,那么代表等差数列结束,开始统计直到当前的最长等差数列的长度,然后进行一次计算能分割的数组数,让sum加上这个结果。

接下来就是上代码了,这个是Python版本的,其他语言可以借鉴思路

class Solution(object):
    # 基础思路是这样的,首先,查找第一个等差数列子数组,假设找到的第一个等差数列子数组长度是5,那么这个长度5的子数组可以划分为(5-5+1)(等差数列长度5时)+(5-4+1)(长度为4时)+(5-3+1)(长度为3时),通过如上可以找到规律,长度为n的等差数列子数组,可以有(n-n+1)+(n-(n-1)+1)+....(n-3+1),也即为1+2+3+....+(n-3+1),可以通过等差数列求和公式快速计算(n-2)+(n-2)*(n-3)/2
    # 思路即为找到所有的连续最长等差子数列,然后通过上述算法得出每一段的数列所能分割的数列和,即为得总数
    # 统计是否为等差数列的方法是,计算前一个数与更前一个数的差是够相同,是则为等差数列
    def numberOfArithmeticSlices(self, A):
        if len(A) < 3:
            return 0
        sum = 0
        length = 2
        cha2 = A[1] - A[0]
        #cha2 = A[2] - A[1]
        for i in range(2,len(A)):
            cha1 = cha2
            cha2 = A[i] - A[i-1]
            if cha1 == cha2:
                length = length + 1
            else:
                if length > 2:
                    sum = sum + length-2 + (length-2)*(length-3)/2
                length = 2
        if length > 2:
            sum = sum + length-2 + (length-2)*(length-3)/2
        return int(sum)
        """
        :type A: List[int]
        :rtype: int
        """

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值