文章目录
等差数列的个数
添加链接描述
法一:滑动窗口+等差求和公式
法二:dp
滑动窗口和dp题解
等差数列划分 II - 子序列
很难,看题解学习一下。
题解
最长等差子序列
添加链接描述
思露:
最优子结构,重叠子问题,无后效性
状态:数组中的每个元素
定义dp[i]:前i个数的定差子序列的最大长度
选择:对于当前的第i个数,所有的j,满足0<j<i && arr[i]-arr[j]=diff
,则dp[i]=dp[j]+1,所以dp[i]取所有情况的最大值。
base case dp[…]=1
return :dp[…]中的最大值
由于 arr.length最大为 10^5,下面写法二重循环会超时。
class Solution {
public int longestSubsequence(int[] arr, int difference) {
int ans=0;
int n=arr.length;
int[]dp=new int[n];
Arrays.fill(dp,1);
for (int i=1;i<n;i++){
for (int j=0;j<i;j++){
if (arr[i]-arr[j]==difference){
dp[i]=Math.max(dp[j]+1,dp[i]);
}
ans=Math.max(ans,dp[i]);
}
}
return ans;
}
}
时间复杂度优化
上面的写法是将arr数组的下标作为dp数组的下标,所以需要遍历[0,i]找arr[j],现在的优化自然是想,该怎么样才能不用遍历[0,i]?
将arr[j]作为dp数组的下标即可
此时:dp[i]=dp[i-diff]+1;
另外,因为arr的数值范围较大,所以用map替代dp数组可以节省空间开销。
import java.util.HashMap;
import java.util.Map;
class Solution {
public int longestSubsequence(int[] arr, int difference) {
int n=arr.length;
Map<Integer,Integer>map=new HashMap<>();
int ans=1;
for (int i=0;i<n;i++){
map.put(arr[i],map.getOrDefault(arr[i]-difference,0)+1);
ans=Math.max(ans,map.get(arr[i]));
}
return ans;
}
}