1027.最长等差数列 (Medium)*
题目描述*

标签*
动态规划
思路 & 代码*
dp 又来了。。。
如果 dp[i] 表示 i 结尾的最长等差数列长度,状态转移要怎么写?所以应该是要用二维 dp[i][j] 表示 i 结尾的公差为 j 的最长等差序列长度。给定了元素的范围 [0, 10000],所以我们就把差值加上偏移 10000 作为第二维。这里优化空间的话可以用哈希表代替内层数组。
还有一种思路是,对于一个等差数列,确定了前两项就确定了后续的值,所以我们每次选两个元素作为数列开头值,求后面的值在数组中的位置。
class Solution {
public:
int longestArithSeqLength(vector<int>& nums) {
int n = nums.size();
if(n < 3) {
return n;
}
vector<vector<int>> dp(n, vector<int>(20001, 0));
int res = 0;
for(int i = 1; i < n; i++) {
for(int j = 0; j < i; j++) {
int dist = nums[i] - nums[j] + 10000;
if(dp[j][dist] > 0) {
dp[i][dist] = max(dp[i][dist], dp[j][dist] + 1);
}else {
dp[i][dist] = 2;
}
res = max(res, dp[i][dist]);
}
}
return res;
}
};
class Solution {
public:
int longestArithSeqLength(vector<int>& nums) {
int n = nums.size();
unordered_map<int, vector<int>> hash;
for(int i = 0; i < n; i++) {
hash[nums[i]].push_back(i);
}
int res = 0;
int cnt = 2;
for(int i = 0; i < n - res; i++) {
for(int j = i + 1; j < n - res + 1; j++) {
int diff = nums[j] - nums[i];
if(diff == 0) {
if(hash[nums[i]].size() > res) {
res = hash[nums[i]].size();
}
continue;
}
int next = diff + nums[j];
int preIndex = j;
bool found = false;
while(hash.count(next)) {
auto& tmp = hash[next];
for(auto& idx : tmp) {
if(idx > preIndex) {
preIndex = idx;
cnt++;
next += diff;
found = true;
break;
}
}
if(!found) {
break;
}
found = false;
}
res = max(res, cnt);
cnt = 2;
}
}
return res;
}
};
最后更新: July 23, 2022