经典面试题---字符串系列(一)---删除字符串

题目:删除字符串中的"b"和“ac”,需要满足如下的条件
1  字符串只能遍历一次
2 不能够使用额外的空间
例如:
1 acbac ===>" "
2 aaac  ===>"aa"
3 ababac ===>"aa"
4 bbbbd  ===>"d"


我的解答程序如下:

<span style="font-size:18px;"><pre name="code" class="cpp"><span style="font-size:18px;">#include <stdio.h>
#include <stdlib.h>
void delete_char(char *str)
{
    int i=0,j=0; //i表示不会删除字符的位置
    for(i=0;str[i]!='\0';i++)
    {
        if(str[i]!='a'&&str[i]!='b')
        {
            str[j] = str[i];
            j++;
        }
        else if(str[i]=='a'&&str[i+1]!='c')
        {
            str[j] = str[i];
            j++;
        }
        else
        {
            if(str[i]=='a')
            {
               str[i]='\0';
               i++;
            }
            str[i]='\0';

        }
    }
    str[j]='\0';

}
int main()
{
    char st[20]="\0";
    printf("enter char:");
    gets(st);
    delete_char(st);
    printf("output:%s",st);
    return 0;
}</span>
</span>

 

我试过了,结果能够输出。

经过分析,我发现这段程序效率不高。
看到了别人的分析,我立刻清晰了起来,在这里贴上:转载,非原创,但很具有参考性。

题目解析:

首先要明白从字符串中删除某些字符该如何实现,显而易见我们可以把保留的字符拷贝新的字符串中来实现删除。但是题目要求不能使用额外的空间。那就是将要删除的字符全部交换到字符串的尾部,然后设置一个'\0'表示字符串的结尾。


其次,如果要删除的都是单个字符的字符串,就很直接:我们使用i和j两个变量遍历字符串,i表示不会删除的字符的位置,j从0开始,只要i所在位置的字符不是要删除的字符,就str[j]=str[i](str表示字符串),然后j++指向下一个位置。一次遍历即可,不需要额外申请空间,只需要两个变量。


但是,现在删除的字符串中有多个字符的,如:“ac”。那要如何处理呢?这里介绍一个小技巧:状态机。这里,我们有两个状态:ONE和TWO。TWO表示,前一个字符时‘a’的状态,其他的都用ONE表示。还是采用前面所描述的遍历方法:


  1. 如果当前状态为ONE,则拷贝:str[j]=str[i];但如果当前字符满足以下两种状态的任一个,则不进行拷贝:

    • 当前字符是‘a’,我们要考虑下一个字符是c

    • 当前字符是‘b’,因为我们要删除b

  2. 如果当前状态为TWO:

    • 当前字符不是‘c’,那么我们要先拷贝前一个字符‘a’

    • 然后考虑当前字符,如果不是‘b’或者‘a’,则拷贝字符


代码如下:

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">#include <stdio.h>
#include <stdlib.h>
#define ONE 1
#define TWO 2
void stringFilter(char *str)
{
    int state = ONE; //初始状态为one,前一个字符不是'a'
    int j = 0;
    int i=0;
    for(i=0;str[i]!='\0';i++)
    {
        if(state==ONE&&str[i]!='a'&&str[i]!='b')
        {
            str[j]=str[i];
            j++;
        }
        //当前状态为TWO
        if(state==TWO&&str[i]!='c')
        {
            str[j]='a';
            j++;
            if(str[i]!='a'&&str[i]!='b')
            {
                str[j]=str[i];
                j++;
            }
        }
        state = (str[i] == 'a')? TWO:ONE;//状态转换
    }
    if (state==TWO) //要考虑最后字符为a的情况
    {
        str[j] = 'a';
        j++;
    }
    str[j]='\0';
}
int main()
{
    char st[20]="\0";
    printf("enter char:");
    gets(st);
    stringFilter(st);
    printf("output:%s",st);
    return 0;
}</span></span></span>

输出结果大家自己编译就好了, 本文的状态机的思想是我们需要学的的知识点。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值