双指针,尺取法
一,字符串
题目大意:链接:https://ac.nowcoder.com/acm/contest/20960/1027
小N现在有一个字符串S。他把这这个字符串的所有子串都挑了出来。一个S的子串T是合法的,当且仅当T中包含了所有的小写字母。小N希望知道所有的合法的S的子串中,长度最短是多少。
小N现在有一个字符串S。他把这这个字符串的所有子串都挑了出来。一个S的子串T是合法的,当且仅当T中包含了所有的小写字母。小N希望知道所有的合法的S的子串中,长度最短是多少。
思路:用两个for循环枚举子串的左端点和右端点,如果直接暴力枚举的话,时间复杂度就会到O(n^12)肯定会超时,但是其实不用两个for循环。当区间内刚好包含26个字母的时候,左端点向前移动一个,右端点不动,此时区间内的字母总数肯定是小于等于26的,此时判断区间是否满足条件并且计算区间的长度,如果长度比初始的小就更新答案。
上代码:
#include<bits/stdc++.h> using namespace std; int a[30]={0}; bool check() { for(int i=0;i<=25;i++) { if(a[i]==0) return 0; } return 1; } int main() { string s; cin >> s; int len=s.length(); int ans=len; int r=0; for(int l=0;l<len;l++) { while(r<len&&!check()) { a[s[r]-'a']++; r++; } if(check()) ans=min(ans,r-l); a[s[l]-'a']--; } cout << ans << endl; return 0; }二.丢手绢
题目大意:链接:https://ac.nowcoder.com/acm/contest/20960/1030
第一行一个整数N,表示有N个小朋友玩丢手绢的游戏。
接下来的第2到第n行,第i行有一个整数,表示第i-1个小朋友顺时针到第i个小朋友的距离。
最后一行是第N个小朋友顺时针到第一个小朋友的距离。
第一行一个整数N,表示有N个小朋友玩丢手绢的游戏。
接下来的第2到第n行,第i行有一个整数,表示第i-1个小朋友顺时针到第i个小朋友的距离。
最后一行是第N个小朋友顺时针到第一个小朋友的距离。
注意事项:因为要用到约瑟夫环,所以n个小朋友的话第一个小朋友编号是0;
#include<bits/stdc++.h> using namespace std; int a[300]; int main() { int sum=0; int n,a[100010]; cin >> n; for(int i=0;i<=n;i++) { scanf("%d",&a[i]); sum+=a[i]; } int r=0,dist=0; int ans=0; for(int l=0;l<=n;l++) { while(ans<sum/2) { ans+=a[r%n]; r++; } dist=max(dist,min(ans,sum-ans)); ans-=a[l]; } cout << dist << endl; return 0; }