424. 替换后的最长重复字符
给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。
如果我们按序遍历每个字符开始计算符合条件的子串长度,对于每个子串,我们只需要以它的第一个字符为不变字符。思路简单,代码清晰,耗时巨长,加了一个遇连续相同字符直接跳过,以及i到达的字符开始的子串不可能为最大时结束,才勉强AC
int characterReplacement(string s, int k) { int n=s.length(); int ans=0; for(int i=0;i<s.length();i++){ if(i>0&&s[i]==s[i-1])continue; if(s.length()-i+k<=ans)return ans; char c=s[i]; int tmp=0; for(int j=i+1;j<s.length();j++){ if(s[j]!=c)tmp++; if(tmp>k){ ans=max(ans,j-i); break; } } if(tmp<=k) ans=max(ans,min((int)s.length(),(int)s.length()-i+k-tmp)); } return ans; }
这题是典型的双指针问题,或者,滑动窗口问题。不需要保存每一个窗口内的字母出现的最大值,因为字母一定是从右边新添的字符里出现,而且只有当窗口内出现了比历史更多的字母数时,答案才会更新,也就是maxCnt不需要是实时的最大字母数。
int characterReplacement(string s, int k) { int n=s.length(); int ans=0,left=0,maxCnt=0; vector<int> letter(26,0); for(int i=0;i<s.length();i++){ letter[s[i]-'A']++; maxCnt=max(maxCnt,letter[s[i]-'A']); if(i-left+1-maxCnt>k){ letter[s[left]-'A']--; left++; } ans=max(ans,i-left+1); } return ans; }
457. 环形数组循环
给定一个含有正整数和负整数的环形数组 nums。 如果某个索引中的数 k 为正数,则向前移动 k 个索引。相反,如果是负数 (-k),则向后移动 k 个索引。因为数组是环形的,所以可以假设最后一个元素的下一个元素是第一个元素,而第一个元素的前一个元素是最后一个元素。
确定 nums 中是否存在循环(或周期)。循环必须在相同的索引处开始和结束并且循环长度 > 1。此外,一个循环中的所有运动都必须沿着同一方向进行。换句话说,一个循环中不能同时包括向前的运动和向后的运动。
原方法:
用一个数组vis记录
vis[i]=k表示 结点 i 是从下标 k 为起始点出发所能到达的路径上的点
每次从未探索过的i出发找大于1的环
bool circularArrayLoop(vector<int>& nums) { int n=nums.size(); vector<int> vis(n,-1); for(int i=0;i<n;i++) { if(vis[i]>=0&&vis[i]<i)continue; int t=i; bool flag=nums[i]>0?true:false; while(flag==(nums[t]>0)){ //flag保证同方向 if(vis[t]==i){ int len=0; int k=(t+nums[t]+n)%n; while(k<0)k=(k+n); //保证下标为正 while(k!=t){ k=(k+nums[k]+n)%n; while(k<0) k=(k+n); len++; if(len>0) return true; } //计算环的长度 break; //从i出发仅有1单位长度的环,继续从i+1开始找 } if(vis[t]!=-1)break; //跑到之前走过的路上去了,之前无解,这次也无解 vis[t]=i; t=(t+n+nums[t])%n; while(t<0)t=(t+n); } } return false; }
改进方法:既然是双指针的问题,又有环,那快慢指针肯定没跑了
int idx(int i, int dx,int n){ if(dx>0)return (i+dx)%n; else return (i-abs(dx)%n+n)%n; } bool circularArrayLoop(vector<int>& nums) { int n=nums.size(); vector<int> vis(n,-1); for(int i=0;i<n;i++) { if(vis[i]!=-1)continue; int slow=i,fast=i; while(nums[slow]*nums[fast]>0&&nums[slow]*nums[idx(fast,nums[fast],n)]>0){ slow=idx(slow,nums[slow],n); if(vis[slow]!=-1&&vis[slow]!=i)break;vis[slow]=i; fast=idx(fast,nums[fast],n); if(vis[fast]!=-1&&vis[fast]!=i)break;vis[fast]=i; fast=idx(fast,nums[fast],n); if(vis[fast]!=-1&&vis[fast]!=i)break;vis[fast]=i; if(fast==slow){ if(idx(slow,nums[slow],n)!=slow)return true; break; } } } return false; }
待更新。。。