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

最新文章

  1. 在执行xp_cmdshell的过程中出错,调用'LogonUserW'失败,错误代码:'1909'
  2. 王爽 &lt;&lt;汇编 语言&gt;&gt; 13.6 BIOS中断例程应用
  3. PHP连接MySQL报错:SQLSTATE[HY000] [2002] Can&#39;t connect to local MySQL server through socket &#39;MySQL&#39; (2)
  4. adb怎么判断是否有root权限,并更改system/app内容
  5. WordPress主题制作教程9:文章形式
  6. 调试WEB APP多设备浏览器(转)
  7. msSQL数据库备份还原小结
  8. JS设置打印页面并调用本地打印机打印页面
  9. C:\WINDOWS\system32\drivers\etc\hosts host文件夹里面的内容是什么?
  10. Struts1 中实现Action跳转地址栏变化的方法
  11. [TYVJ] P1025 单数?双数?
  12. PHP中使用CURL(一)
  13. Redis基础学习(三)&mdash;Key操作
  14. GUI(GroupLayout 分组布局)
  15. CheckedTextView文字不居中的问题
  16. C# Math的说有函数 以及说明
  17. Linq to SQL -- Group By、Having和Exists、In、Any、All、Contains
  18. Spring Aop分析
  19. LVM : 快照
  20. js常用的工具函数

热门文章

  1. CentOS 6.5下Squid代理服务器的安装与配置
  2. BZOJ1053:反素数(数学)
  3. 三、java面向对象编程_1
  4. php生成word
  5. 外网IP和内网IP的区别
  6. [网络流24题] 最长k可重区间集
  7. 图片截取插件Cropper
  8. python笔记之psutil模块
  9. 奇葩字符 &quot;a๎๎๎๎๎๎๎๎๎๎๎๎๎๎๎๎๎๎๎&quot; 的简单分析
  10. [转载]代码编辑器Sublime Text 3 免费使用方法与简体中文汉化包下载