加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

[C/C++]如何去除重复出现的字符,而且保持原序列的相对位置不变

(2015-08-25 12:16:51)
标签:

c/c

stl

c语言

分类: Software/MASM/C/CPP

这天,在bat群里面有个哥们提出一个问题:

//string str = "zhaohaoyang";

//如何去除重复出现的字符,而且保持原序列的相对位置不变,例如这个例子会变成zyng

当时首先想到的,脑袋中出现得竟然是map容器,因为它不会存储重复的key值,于是,我写起下面这段代码:

    map vector > char_repeator;

    int input;

    int number = 0;

    while(EOF != (input = getchar())){

        char_repeator[input].push_back(++number);

    }

    for(map vector >::const_iterator iter = char_repeator.begin(); iter!= char_repeator.end(); ++iter){

        if(1 == iter->second.size())

            cout << iter->first;

    }

cout << endl;

输出结果:

http://a3.qpic.cn/psb?/V11QIa622wMGNE/F64vzAbzQwICNc*pO1HF5JFs7fMVWi75Cyt8J.5*v3M!/b/dGIBAAAAAAAA&ek=1&kp=1&pt=0&bo=vgBBAAAAAAADANo!&su=0223230897&sce=0-12-12&rf=2-9

我们想得到的结果是eca,没想到最后却是ace,这是因为map会自动对key排序。

此路不通,寻问别人。

甘哥说,可以用unique,于是我上网找了一篇文章,了解了一下,开干,写了下面这段代码:

       string str = "zhaohaoyang";

       vector vecch(str.begin(), str.end()); //根据迭代器的起始位置和终止位置来定初始化一个容器

       vector::iterator it = vecch.begin();

       for (; it != vecch.end(); ++it)

       {

              cout<<*it;

       }

       cout << endl;

       sort(str.begin(),str.end());

       cout << str <<endl;

       str.erase(unique(str.begin(), str.end()), str.end());

       cout << str <<endl;

       输出结果:

       http://a3.qpic.cn/psb?/V11QIa622wMGNE/Pb6qq0X59avvLmc4x.S6BjPd*9DJ4.K6413z.dWcfPQ!/b/dGoAAAAAAAAA&ek=1&kp=1&pt=0&bo=agAvAAAAAAADAGA!&su=039207617&sce=0-12-12&rf=2-9

结果依然不理想,和map的结果类似,unique只对相邻且重复的字符去重得唯一,但不能对不相邻的去重得唯一,

故还是不行。

此路不通,再次寻问别人。

晓卫说,可以创建三个数组来记录,用数组模拟散列,我一听晕了,真得能做到吗?怀着半信半疑的态度把代码写完,发现:

    char orgin[] = {"zhaohaoyang"};//应该输出zyng

    char temp[128];//按序暂存字符

    char dest[128];//存放结果

    int countor[128] = {0};//统计字符个数

    int length = strlen(orgin);

    memset(temp, '\0', sizeof(dest));

    memset(dest, '\0', sizeof(dest));

    int j = 0;

    for(int i = 0; i != length; ++i){

        if( 1 == ++countor[orgin[i]])

            temp[j++] = orgin[i];

    }

    j = 0;

    for(int i = 0; temp[i] != '\0'; ++i)

        if(1 == countor[temp[i]])

            dest[j++] = temp[i];

    printf("\n%s\n", orgin);

printf("%s\n", dest);

 

输出结果:

http://a3.qpic.cn/psb?/V11QIa622wMGNE/5C98L9N1kBgcyrSMp2lVXnbk3eBwSYBnnE3nDWgK0Ec!/b/dGIBAAAAAAAA&ek=1&kp=1&pt=0&bo=aQAeAAAAAAADAFI!&su=0254039841&sce=0-12-12&rf=2-9

发现真得成功了。主要是需要一个数组来存放字符的顺序,然后取出现次数为1的字母加进目标数组就行了。

后来想想,因为我们的目的是去重,所以一共128个可输入字符(可见字符其实是93个),每个字符至多出现一次,所以我们得到的最后字符串并不繁琐,反而很简单,从我们创建的字符数组的大小是128就可以得知,得到的最后字符串的大小最多是128

 

自己转了一个大弯子,本来用C语言老老实实写的程序,非得用C++,这,你说能不郁闷吗?

在bat群里的一哥们也提出一种方案,用vbs的len(replace(str,z,””))依次替换每一个字符后计算长度来判断是否重复,

这个方法理论上是可以的,只不过效率可能略低,因为要依次替换,还要计算长度。但是也是一种思路,多动脑毕竟是好事。

所以,思路还需灵活,思路决定出路,我还需要多多学习,最后,感谢各位兄弟的帮忙。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有