A sequence of numbers 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 sequences:数组
1, 3, 5, 7, 9 7, 7, 7, 7 3, -1, -5, -9
The following sequence is not arithmetic.less
1, 1, 2, 5, 7
A zero-indexed array A consisting of N numbers is given. A subsequence slice of that array is any sequence of integers (P0, P1, ..., Pk) such that 0 ≤ P0 < P1 < ... < Pk < N.this
A subsequence slice (P0, P1, ..., Pk) of array A is called arithmetic if the sequence A[P0], A[P1], ..., A[Pk-1], A[Pk] is arithmetic. In particular, this means that k ≥ 2.spa
The function should return the number of arithmetic subsequence slices in the array A.code
The input contains N integers. Every integer is in the range of -231 and 231-1 and 0 ≤ N ≤ 1000. The output is guaranteed to be less than 231-1.blog
Example:three
Input: [2, 4, 6, 8, 10] Output: 7 Explanation: All arithmetic subsequence slices are: [2,4,6] [4,6,8] [6,8,10] [2,4,6,8] [4,6,8,10] [2,4,6,8,10] [2,6,10]
分析element
又是一个光题目就得看半天的算法题,前面能够直接无视,直接看它给出的例子就知道这题到底要求什么了。看了下解答,方法是利用dp。leetcode
最少须要记住两个参数,序列的第一个或者最后一个元素,以及这个序列中的公共差。
f[i][d]
denotes the number of arithmetic subsequences that ends with A[i]
and its common difference is d
.
下一步是寻找状态转移表达式已创建子问题之间的桥梁。试想若是咱们如今想要把一个新元素A[i]插入到一个现有的arithmetic sequence中来造成一个新的arithmetic sequence,那么只有在A[i]和原来的sequence中最后一个元素的差等于其公共差的状况下才能造成新的arithmetic sequence。
这里比较难理解的即是 T(i, d) = summation of (1 + T(j, d))
as long as 0 <= j < i && d == A[i] - A[j]
. 这个式子,仍是用个例子来讲明比较好,若是当前的 j 是 3,公差是1的话 :
1,2,3,4
2,3,4
两个可能。3,4由于元素个数少于3个因此不构成arithmetic sequence,如今咱们将A[i]=A[5]=5加入以构成新的arithmetic sequence,
1,2,3,4,5
2,3,4,5
3,4,5
多了一个,并非彻底等于以前的T(j, d)。
dp的特性,子问题之间有重复,和分治不一样。
代码
public int numberOfArithmeticSlices(int[] A) { int res = 0; Map<Integer, Integer>[] map = new Map[A.length]; for (int i = 0; i < A.length; i++) { map[i] = new HashMap<>(i); for (int j = 0; j < i; j++) { long diff = (long)A[i] - A[j]; if (diff <= Integer.MIN_VALUE || diff > Integer.MAX_VALUE) continue; int d = (int)diff; int c1 = map[i].getOrDefault(d, 0); int c2 = map[j].getOrDefault(d, 0); res += c2; map[i].put(d, c1 + c2 + 1); } } return res; }
map数组用来存储中间计算结果T(i, d),数组的index对应i,表示arithmetic sequence以A[i]结束;key是公共距离差d,value是arithmetic sequence的个数,也就是T(i, d)。也就说用了map数组一会儿存储了三个基本信息,厉害了。
这题真的好难。