牛妹收到了一个项链,这个项链一共有n个珠子,每个珠子都有一个颜色。这n个珠子构成了一个环。
不知为何,牛妹想从项链上截下一段连续的珠子,但是牛妹不喜欢同一个颜色出现两次,所以截下来的这一段珠子中没有相同的颜色。现在牛妹想知道她可以截下的最长的一段珠子为多长?
特别的,与第1个珠子相邻的珠子为第2个,第n个珠子。
与第n个珠子相邻的珠子为第n-1个,第1个珠子。
4,[3,1,1,2]
3
牛妹可以选择在第3个珠子的左边和右边各切一刀,截取第4个,第1个和第2个珠子连起来的连续珠子。
第一个参数n代表珠子个数
第二个参数vector<int> a包含n个元素代表每个珠子的颜色。
#include <unordered_map> class Solution { public: /** * 牛妹的项链 * @param n int整型 * @param a int整型vector * @return int整型 */ int solve(int n, vector<int>& a) { unordered_map<int, int> M; int s=0, k=0; for(int i=0;i<(n<<1);i++){ if(M.find(a[i%n]) != M.end()){ k = max(k, M[a[i%n]]); s = max(s, i-k); } M[a[i%n]] = i; } return s; } };
class Solution { public: /** * 牛妹的项链 * @param n int整型 * @param a int整型vector * @return int整型 */ int solve(int n, vector<int>& a) { map<int, int> Map; int l = n, Max = 1; for (int r = n; r < 2 * n; r++) { a.push_back(a[r - n]); if (r == n) while (Map.find(a[l]) == Map.end()) {Map[a[l]] = l; l--;} else { if (Map.find(a[r]) != Map.end()) l = max(l, Map[a[r]]); Map[a[r]] = r; } Max = max(Max, r - l); } return Max; } };
class Solution: def solve(self, n, a): dp = [0] * n # 记录每个位置的最大值 dp[0] = 1 # 第一个位置初始值为1 ind = 0 # 记录没有颜色重复的初始位置,初始值为0 for i in range(1, n): # 从第二个位置开始更新dp if a[i] in a[ind:i]: # 第i个颜色是否为重复颜色 c = a[ind:i] # 将没有颜色重复的这一段截取出来 c.reverse() # 反转,为了下一步得到和第i个颜色重复的珠子的位置 ind += (len(c) - 1) - c.index(a[i]) # ind加上 和第i个颜色重复的珠子在没有颜色重复区间的位置,得到和第i个颜色重复的珠子在整串珠子中的位置 dp[i] = i - ind # 得到dp[i] ind += 1 # 更新没有颜色重复的初始位置 else: # 第i个颜色没有重复时 dp[i] = i + 1 - ind # 考虑将首位两端连接的情况 aa = a[-dp[-1]:] # 截取最后一个位置能得到的最大长度,在考虑从第一个开始往后的颜色有无重复即可 j = 0 while a[j] not in aa: # 没有重复,将dp[i]加一即可,有重复就停止 dp[-1] += 1 j += 1 return max(dp) # 返回dp[i]的最大值,即最大的长度
int solve(int n, vector<int>& a) { // write code here vector<int> dp(n+1, 0); // dp[i]表示以第i个珠子结尾的最长单色长度 dp[1]=1; int res=0; for(int i=2;i<=n;i++){ // 单向遍历搜索,以i结尾的最长长度 int pre=i-1; for(; pre>i-1-dp[i-1] && a[pre-1]!=a[i-1];pre--){ // 判断前dp[i-1]个珠子是否和第i个珠子同色, 同色就停下 } dp[i]=i-pre; // 第i个珠子结尾的最长长度 res=max(res, dp[i]); } int i=1; // 还没有判断首尾相连的情况,所以遍历首部的几个珠子。 // 符合条件的是,前i个珠子都不同色(若存在同色,则不用继续向后了),并且不在尾部的那个序列中 for(;i>=dp[i] && i<n-dp[n];i++){ int j=n; for(;j>n-dp[n] && a[i-1]!=a[j-1];j--){ // 判断第i个珠子是否和尾部的珠子同色 } if(j>n-dp[n]){ i++; break; } } res=max(res, dp[n]+i-1); // i是首部符合条件的后一个,所以减1 return res; }
int solve(int n, vector<int>& a) { map<int, int> mm; int ret = 0; int last = 0; for(int i = 0; i < n * 2; i++){ auto itr = mm.find(a[i%n]); if(itr != mm.end()){ last = max(last, itr->second); ret = max(ret, i - last); } mm[a[i%n]] = i; } return ret; }每个位置作为结尾,找到构成最长的起始位置last, last应该保证不能有元素重复,mm保留每个值最后出现位置