https://leetcode-cn.com/problems/arithmetic-slices-ii-subsequence/
思路:就知道是dp,但是差一步没写出来,唉。考虑用
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示以
n
u
m
s
[
i
]
nums[i]
nums[i]结尾公差为
j
j
j的长度
>
=
2
>=2
>=2的子序列个数。那么可以枚举等差数列的最后两项:
n
u
m
s
j
、
n
u
m
s
i
nums_j、nums_i
numsj、numsi。计算其公差
d
i
s
=
n
u
m
s
i
−
n
u
m
s
j
dis=nums_i-nums_j
dis=numsi−numsj,又知道以
n
u
m
s
j
nums_j
numsj结尾公差为
d
i
s
dis
dis的长度
>
=
2
>=2
>=2的子序列个数为
d
p
j
,
d
i
s
dp_{j,dis}
dpj,dis,显然这些子序列再加上
n
u
m
s
i
nums_i
numsi就可以构成满足题意的子序列,因此可以令
a
n
s
+
=
d
p
j
,
d
i
s
ans+=dp_{j,dis}
ans+=dpj,dis。而
[
n
u
m
s
j
,
n
u
m
s
i
]
[nums_j,nums_i]
[numsj,numsi]构成了新的长度为2的子序列,因此
d
p
i
,
d
i
s
+
=
d
p
j
,
d
i
s
+
1
dp_{i,dis}+=dp_{j,dis}+1
dpi,dis+=dpj,dis+1。
class Solution {
public:
int numberOfArithmeticSlices(vector<int>& nums) {
int n=nums.size();
using ll=long long;
vector<unordered_map<ll,int>> dp(n);
int ans=0;
for(int i=1;i<n;i++)
{
for(int j=0;j<i;j++)
{
ll dis=(ll)nums[i]-nums[j];
int cnt=0;
if(dp[j].count(dis))
cnt=dp[j][dis];
ans+=cnt;
dp[i][dis]+=cnt+1;
}
}
return ans;
}
};