如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。
例如,以下数列为等差数列:
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
"""