动态规划——446. Arithmetic Slices II

来源:互联网 发布:java web模块化开发 编辑:程序博客网 时间:2024/06/14 05:29

终于又做了一道 [HARD],新学了hash_map……

题目描述

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, 97, 7, 7, 73, -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.

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: 7Explanation: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]


这道题厉害了,求等差数列(数列长度要大于等于3),而且,这些数字不需要是连续的,比如{1,2,3,3}如果是连续的等差数列,返回1[1,2,3];不连续返回

2[1,2,3]和[1,2,3]——因为有两个3……


解题思路

我想过O(n^3)的算法,但是由于一些特例没考虑到,过不了。鼓捣一天之后,终于决定看看dalao们的做法,运用到了[结合hash_map的动态规划,真是活久见]

具体做法是这样的:

1)定义vector<hash_map<int , int> >  result,保存前后两个数的差值和到目前为止这个差值有了多少个数列

2)在遍历过程中,因为考虑到是不连续数列,需要遍历当前值的左侧的所有值,给对应的差值的数列数+1(这里应用到hash_map的一个特点,刚刚弄明白,会在代码里说明)

3)考虑差值溢出的情况,每个值都是int,但是负数-负数得到的负数可能太大了,变成正数,这要考虑到int是32位的(具体可以自行查找计算机中数字的表示)

4)把所有差值的数列都加起来即为所求


分析图如下:



i与j之间的diff表示已经有两个数在该队列里,如果这时候j的diff后的队列不为0,那么该队列加上i位置的数最少是三个的,此时,要把j的diff的数列加到总数列去。


代码如下

int numberOfArithmeticSlices(vector<int>& A) {vector<unordered_map<int, int> > result(A.size());int num = 0;for (int i = 0; i < A.size(); i++) {for (int j = 0; j < i; j++) {long diff = A[i] - A[j];if (diff > INT_MAX || diff < INT_MIN)continue;elseresult[i][((int)diff)] += 1;//hash 的 特性,一开始应该是空的(diff都应该不存在)//但是用result【i】【diff】时自动产生了,//并且result【i】【diff】= 0//已经验证了这一点,map也是if (result[j].find(((int)diff)) != result[j].end()) {//如果去掉这个if,每次result【j】【diff】//都产生一个result【j】【diff】 = 0,//会超出空间限制result[i][diff] += result[j][diff];num += result[j][((int)diff)];}}}return num;}



附加:

hash_map 就是 unordered_map:特性是查找复杂度为常数

map:存储为有序的

以上两个结构,声明结构之后,就可以用[]初始化,result[x];//此时生成了x对应的值,默认为0


再复习一下优先队列:

priority_queue<intvector<int>, less<int> > t;   //大到小

priority_queue<int > t;  //小到大


0 0