此次是将动态规划题目,以建立dp表放在哈希表中进行处理,能极大的减少时间复杂度
在一个arr数组中去寻找以diff为定差的子序列
那么在开始,我依旧按照以前思路进行思考,建立dp表,依旧有dp[i]=max(dp[j]+1,dp[i])中进行查找dp[i],dp[i]表示以i位置的元素为结尾的子序列中,最长的等差子序列的长度。
可是往后做就会发现这个时间复杂度是O(N*N);时间复杂度很高,在leetcode上不会通过,那么就可以考虑到建立哈希表,在哈希表中进行dp就可以将时间复杂度变为O(N);
hash[arr[i]]=hash[arr[i]-difference]+1;
那么就开始考虑优化方案,因为在这之前,我要每次都考虑取到[0-j]区间中,保证能取到最后一个元素的b元素。即下表为j,那么我们可以在这个条件下,1.每次都绑定元素b与他的下标j一起放入到哈希表中,或者2.将i位置的元素与下标进行绑定一起放入到哈希表中,这样在哈希表中进行dp,且寻找元素的时间复杂度是O(N)
初始化就是初始化dp的第一个元素为1,即当数组arr只有一个元素的时候,其子序列也是1
返回值就是这个dp表中的最大值
class Solution {
public:
int longestSubsequence(vector<int>& arr, int difference) {
//在哈希表里做dp
int n=arr.size();
map<int,int> hash;//时间复杂度O(N); arr[i]-dp[i]
hash[arr[0]]=1;
int ret=1;
for(int i=1;i<n;i++)
{
hash[arr[i]]=hash[arr[i]-difference]+1;//将dp[i]里面的值更新成dp[j],若找到这个元素就hash这个元素的下标,若找不到,就返回0+1
ret=max(ret,hash[arr[i]]);
}
return ret;
}
};
hash[arr[0]]=1; //其中k值就是对应数组中的元素,value就是dp[i]所含有最大的次数。
hash[arr[i]]=hash[arr[i]-difference]+1;//将dp[i]里面的值更新成dp[j],若找到这个元素就hash这个元素的下标,若找不到,就返回0+1
class Solution {
public:
int lenLongestFibSubseq(vector<int>& arr) {
int n=arr.size();
//优化,将数组所有元素与下标绑在一起
map<int,int> hash;
for(int i=0;i<n;i++)
hash[arr[i]]=i;//将所有元素扔进哈希表,里面k值就是arr的元素,value就是元素的下标
vector<vector<int>> dp(n,vector<int>(n,2));//只用得到i<j的表格,对角线以上的元素,所以全部都初始化为2
int ret=2;
for(int j=2;j<n;j++)//确定最后一个元素的位置
{
for(int i=1;i<j;i++)//确定倒数第二个元素的位置
{
int a=arr[j]-arr[i];
if(a<arr[i]&&hash.count(a))
dp[i][j]=dp[hash[a]][i]+1;//a元素的下标k
ret=max(ret,dp[i][j]);
}
}
return ret<3?0:ret;
}
};