446. Arithmetic Slices II - Subs
题目
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.
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.
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.
The function should return the number of arithmetic subsequence slices in the array A.
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.
Example:
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]
分析
这是在上一题的基础上做了些变化,也是给定一个数组,找数组中的至少三位的等差数列个数,与上一题不同的是,这次数列的数在数组中不要求连续,中间可以隔其他的数。
思路:
T(i,d)表示到i下标时有多少个相隔d的数列
Base case: T(0, d) = 0 (This is true for any d).
Recurrence relation: T(i, d) = summation of (1 + T(j, d)) as long as 0 <= j < i && d == A[i] - A[j].
看原版的discuss会好易理解一些
代码
public int numberOfArithmeticSlices(int[] A) {
int res = 0;
if(A.length < 2) return 0;
int n = A.length;
Map<Integer, Integer>[] map = new Map[n]; //map中存放的是两个元素的数目,而不是三个元素的数目
for(int i = 0; i < n; ++i){
map[i] = new HashMap();
for(int j = 0; j < i; ++j){
long diff = (long)A[i] - A[j];
if(diff > Integer.MAX_VALUE || diff <= Integer.MIN_VALUE) continue;
int d = (int)diff;
int c1 = map[i].getOrDefault(d, 0); //已经积累的数
int c2 = map[j].getOrDefault(d, 0); //可以生成的数(至少有两个了,加上i上的数就至少三个)
res += c2;
map[i].put(d, c1 + c2 + 1); //自身积累的数+可以生成的数+新二者对
}
}
return res;
}