算法题——字符串删减

题目:


题目要求删除一段字符串中的字母,使得字符串中不存在连续三个或三个以上的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也是正确的)。

posted @ 2023-02-21 17:20  HD0117  阅读(19)  评论(0编辑  收藏  举报