算法题——字符串删减
题目:
题目要求删除一段字符串中的字母,使得字符串中不存在连续三个或三个以上的x,问最少删除多少个字母。
直接遍历
分析:数据量较小,n大小为[3,100],可以直接遍历字符串,设置计数变量cnt,遇到x则cnt加一,没有遇到x则cnt置0(因为此时出现了别的字符,x已经不连续了),如果cnt等于3,那么记录删除个数的变量ans加一,cnt减一,这里cnt减一是因为删去了一个x,连续的还有两个x,并且不确定下一个字符是不是x,因此只能减一不能置0。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
int n,ans,cnt;
string str;
int main()
{
cin>>n>>str;
int l=0,r=n-1;
ans=0,cnt=0;
for(int i=0; i<n; ++i)
{
if(str[i]=='x')
{
cnt++;
if(cnt==3)
{
ans++;
cnt--;
}
}
else
{
cnt=0;
}
}
cout<<ans;
return 0;
}
双指针法
分析:如图,连续的x可以有1个,也可以有多个,当连续的x有多个时,需要删除x至x只剩下连续的两个。假设连续的x有k个,则需要删除k-2个或者0个(当k大于等于3时删除k-2个),因此是删除max(k-2,0)个。
讨论为什么不删除别的字符:删除别的字符,连续个x还是存在,并且如上图相邻的两段连续的x,如果删除它们中间的别的字符,可能两段x会拼接到一起,此时还是需要再删除max(k-2,0)个x。因此删除别的字符无法满足删除最少的字符的要求。
用双指针法写,首先用i遍历字符串,遇到x时,用j从i+1继续遍历x,直到字符不等于x为止,然后ans加上max(k-2,0),最后输出结果。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
string str;
int main()
{
cin>>n>>str;
int ans=0;
for(int i=0; i<n; ++i)
{
if(str[i]=='x')
{
int j=i+1;
while(j<n && str[j]=='x') ++j;
ans+=max(j-i-2, 0);
i=j-1;
}
}
cout<<ans;
return 0;
}
这里如果str[j]为x,j加一,那么下次判断的是str[j+1],如果j+1不是x,跳出循环,此时k=j-i,下次遍历从这段连续的x的末尾开始,i=j-1(i也可以等于j,i=j也是正确的)。