这道题是此题的升级版,之前那题仅仅考虑的是连续的子序列,本题允许非连续子序列的存在。
初略一看,也是采用动态规划方法解决。
例如:
1 2 3 4 5
这个等差数列,在链接中题的结果为6,而在本题的结果为7,包含了非连续等差子序列1 3 5
7 7 7 7 7
此例子中,在链接中题结果为6,在本题的结果中为16,其中例子为:7 7 7 原数列中的第一个7,第二个7,以及第五个7。
因此两道题没有必然上的联系,由此看来要先定义状态,如果仅按照之前的定义为dp[i],则到i+1时不会确定每个公差不同的非连续子序列数的个数,因此需要定义为dp[i][d],表示遍历到nums[i]数时,公差为d的子序列的个数。
转移方程
在进行转移方程确定前,要先提到一个概念。
弱等差子数列:即至少两个元素构成的子数列。
我们首先考虑的都为弱等差子数列,不考虑数列强制长度至少为3的情况。
在[0,...,i-1]任选一个数j,令公差d=nums[i]-nums[j],此时一定要注意dp[i][d]的含义,含义更明显就是以nums[i]结尾的,公差为d的等差子序列数目。因此在i和j之间的关系如下:
dp[i][d]=dp[j][d]+1;
dp[i][d]就是在以nums[j]结尾,公差也为的d的子序列后面加上一个数nums[i],因此,按照状态定义,dp[i][d]为dp[j][d]的所有子序列末尾加上nums[i]都在内,格外再包含子序列{nums[j],nums[i]}。
最后将[0,...,i-1]中的每个i一直相加,状态转移方程为:
初始条件
dp数组开始全为0。
最后结果
以任意数结尾,公差d大于等于1的值的总和result。
代码数据结构:
由于公差d的范围很广,采用map这种hash表示加快相应dp[j][d]的查找。