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]

分析

又是一个光题目就得看半天的算法题,前面可以直接无视,直接看它给出的例子就知道这题到底要求什么了。看了下解答,方法是利用dp。

最少需要记住两个参数,序列的第一个或者最后一个元素,以及这个序列中的公共差。

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

LeetCode446. Arithmetic Slices II - Subsequence的更多相关文章

  1. Arithmetic Slices II - Subsequence LT446

    446. Arithmetic Slices II - Subsequence Hard A sequence of numbers is called arithmetic if it consis ...

  2. [LeetCode] Arithmetic Slices II - Subsequence 算数切片之二 - 子序列

    A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...

  3. LeetCode 446. Arithmetic Slices II - Subsequence

    原题链接在这里:https://leetcode.com/problems/arithmetic-slices-ii-subsequence/ 题目: A sequence of numbers is ...

  4. [Swift]LeetCode446. 等差数列划分 II - 子序列 | Arithmetic Slices II - Subsequence

    A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...

  5. Leetcode: Arithmetic Slices II - Subsequence

    A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...

  6. 446. Arithmetic Slices II - Subsequence

    A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...

  7. 446 Arithmetic Slices II - Subsequence 算数切片之二 - 子序列

    详见:https://leetcode.com/problems/arithmetic-slices-ii-subsequence/description/ C++: class Solution { ...

  8. 第六周 Leetcode 446. Arithmetic Slices II - Subsequence (HARD)

    Leetcode443 题意:给一个长度1000内的整数数列,求有多少个等差的子数列. 如 [2,4,6,8,10]有7个等差子数列. 想了一个O(n^2logn)的DP算法 DP[i][j]为 对于 ...

  9. [LeetCode] Arithmetic Slices 算数切片

    A sequence of number is called arithmetic if it consists of at least three elements and if the diffe ...

随机推荐

  1. shell参数代表什么,如何调试shell?

    $0就是该bash文件名$?是上一指令的返回值$*所有位置参数的内容:就是调用调用本bash shell的参数.$@基本上与上面相同.只不过是“$*”返回的是一个字符串,字符串中存在多外空格.“$@” ...

  2. python的if条件语句的语法和案例

    1.条件语句 缩进用4个空格 if条件: #条件成功, else: #条件不成功 if条件:{ #条件成功, #条件成功, }else{ #条件不成功, #条件不成功, } if的语法就是这样或者是用 ...

  3. [CQOI2009]DANCE跳舞(ISAP写法)

    https://daniu.luogu.org/problemnew/show/3153 #include<queue> #include<cstdio> #include&l ...

  4. Bzoj4763 雪辉

    Time Limit: 39 Sec  Memory Limit: 666 MBSubmit: 151  Solved: 80 Description 上次立下的NOIP退役Flag没有成功   这次 ...

  5. 对于最近一星期jsp培训有感

    这周上课是jsp的培训,找的是外面的一个培训机构的讲师,人挺好的,讲的也不错,不过交给我们的任务是一星期做出一个网站模型——新闻发布系统. 由于我们组本科学计算机的人实在太少了,所以这个重担落在我的身 ...

  6. 【leetcode 简单】 第八十八题 猜数字大小

    我们正在玩一个猜数字游戏. 游戏规则如下: 我从 1 到 n 选择一个数字. 你需要猜我选择了哪个数字. 每次你猜错了,我会告诉你这个数字是大了还是小了. 你调用一个预先定义好的接口 guess(in ...

  7. HTML字体的设置

    CSS字体设置 box-sizing:border #content-box   box-shadow:设置盒子边框的阴影.     字体动作:   font-family:设置字体.比如:‘微软雅黑 ...

  8. Python练习-一个Break跳出所有循环

    Alex大神的需求:三层循环,在最内层循环中使用break,让所有循环结束; # 编辑者:闫龙 i=1; count=0; while 1==i : while 1==i: while 1==i: c ...

  9. UNIX环境高级编程 第13章 守护进程

    守护进程daemon是一种生存周期很长的进程.它们通常在系统引导时启动,在系统关闭时终止.守护进程是没有终端的,它们一直在后台运行. 守护进程的特征 在Linux系统中,可以通过命令 ps -efj ...

  10. 再战CS231-数组的访问

    1.切片访问和整形访问的区别 你可以同时使用整型和切片语法来访问数组.但是,这样做会产生一个比原数组低阶的新数组 import numpy as np # Create the following r ...