LeetCode446. Arithmetic Slices II - Subsequence

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數組一會兒存儲了三個基本信息,厲害了。

這題真的好難。

參考:https://leetcode.com/problems/arithmetic-slices-ii-subsequence/discuss/92822/Detailed-explanation-for-Java-O(n2)-solution

相關文章
相關標籤/搜索