思路:
题目的主要信息:
- 用数组a表示项链的不同颜色,即不同数字表示不同颜色,且首尾相接
- 从数组中取出一段数字都不同的连续子序列,求子序列最长长度,需要注意首尾相接的情况
方法一:动态规划
具体做法:
我们可以将数组首尾相接,组成一个的新数组,就不需要再处理循环了。我们用
表示以第
个珠子结尾的最长连续不相同颜色的长度,遍历新数组,每次判断判断前
个珠子是否和第
个珠子同色,同色则停下,然后记录下最长长度。
class Solution {
public:
int solve(int n, vector<int>& a) {
int res = 0;
for(int i = 0; i < n; i++) //首尾相接
a.push_back(a[i]);
vector<int> dp(2 * n + 1, 0);//dp[i]表示以第i个珠子结尾的最长连续不相同颜色的长度
dp[1] = 1;
for(int i = 2; i <= 2 * n; i++){
int j;
// 判断前i-1个珠子是否和第i个珠子同色,同色则停下
for(j = i - 1; j > i - 1 - dp[i - 1] && a[j - 1] != a[i - 1]; j--);
dp[i] = i - j; //以第i个珠子结尾的最长连续不相同颜色的长度
res = max(res, dp[i]);
}
return res;
}
};复杂度分析:
- 时间复杂度:
,两层循环,每层都是
- 空间复杂度:
,辅助数组dp的长度
方法二:哈希表
具体做法:
因为子序列中元素有互异性,我们可以想到用哈希表来查重。因为数组首尾相接是循环,我们可以考虑遍历长度为2倍数组长度,然后取模。遍历的时候,如果遇到一个数字在哈希表中出现过,我们可以比较它最后出现的位置,将现在的位置减去最后出现的作为一次连续子序列的长度,不断维护最大值。同时,每次遇到一个元素之后,需要用哈希表记录其最后一次出现的位置。
class Solution {
public:
int solve(int n, vector<int>& a) {
unordered_map<int, int> mp;
int res = 0;
int last = 0; //最长子序列的起始位置
for(int i = 0; i < 2 * n; i++){
if(mp.find(a[i % n]) != mp.end()){
last = max(last, mp[a[i % n]]); //找到它最后出现的位置
res = max(res, i - last); //维护最大值
}
mp[a[i % n]] = i; //记录每个值最后出现的位置
}
return res;
}
};复杂度分析:
- 时间复杂度:
,一次遍历,循环长度为
- 空间复杂度:
,最坏情况下所有元素都不同,哈希表最大

京公网安备 11010502036488号