【算法20】在字符串中删除特定的字符
【题 目】输入两个字符串,从第一个字符串中删除第二个字符串中出现的所有字符。例如:输入"they are students." 与 “aeiou”,则应该输出“thy r stdnts.”。
【思 路1】首先我们还是以解决问题为第一要义,寻找最为直观的解决方案,很容易想到的方法就是,对于在第一个字符串中的每一个字符,拿它去查找是否在第二个字符串中出现过,如果是,则删除,如果不是则保留。删除一个字符,要让该字符之后的所有字符逐一向前移位,所以时间复杂度为O(n),对于长度为n的字符串,总的时间复杂度为O(N2).而对于给定的字符,在第二个字符串中查找该字符,如果遍历长度为m的第二个字符串的话,时间复杂度也为O(m),总的时间复杂度为O(mn).
【思 路2】有没有更为高效的方法呢?事实上我们在并没有必要在每次删除一个字符的时候都让后面的字符移动,我们只需要让被删除位置的字符被后面不需要被删除的字符来代替就可以了,相当于我们有一个先头哨兵,它只负责寻找那些不需要被删除的字符,碰到需要删除的就直接跳过,碰到不需要删除的就告诉主力哨兵,主力哨兵负责对于先头哨兵找到的字符给予“接收”位置就行了。具体来说:我们可以设置两个指针pfast(先头哨兵)和pslow(主力哨兵),初始时两个都指向字符串的第一个字符,pfast碰到一个需要删除的字符“视而不见”直接跳过;pfast如果碰到不需要删除的字符,就把该字符复制给pslow,同时pfast后移(继续寻找),pslow(指向下一个位置)。这样整个算法的时间复杂度就可以达到O(n)。
接下来我们要考虑查找的问题,对于char型字符的查找,我们讨论过用长度为256的哈希表来存储字符出现的次数最后高效,详细讨论见【算法19】.这样的查找效率为O(1).好了,删除和查找的问题都解决了,我们很容易写出如下的代码:
1 #include<iostream>
2 #include<string>
3 using namespace std;
4
5 void DelChars(char* pstrSource,char* pstrDel)
6 {
7 if(pstrSource == NULL || pstrDel == NULL)
8 return;
9
10 //建立并初始化哈希表
11 const int hashLength = 256;
12 unsigned int hashList[hashLength];
13 for(int i = 0;i < hashLength;++i)
14 {
15 hashList[i] = 0;
16 }
17
18 //hash表中存储第二个字符串中每个字符出现的次数
19 char *pch = pstrDel;
20 while(*pch != '\0')
21 {
22 hashList[*pch]++;
23 pch++;
24 }
25
26 char *pfast = pstrSource;
27 char *pslow = pstrSource;
28 while(*pfast != '\0')
29 {
30 //如果pfast指向的字符不需要删除,就把其所指的值赋给pslow,两者都向后移
31 //否则,pfast向后移动继续寻找,pslow不动
32 if(hashList[*pfast] == 0)
33 {
34 *pslow = *pfast;
35 pslow++;
36 }
37 pfast++;
38 }
39
40 //非常容易忽视,记得加上字符串结束符!
41 *pslow = '\0';
42 }
43
44 int main()
45 {
46 const int StrMaxLength = 100;
47 cout<<"Enter your first(/resource) string:"<<endl;
48 char strFirst[StrMaxLength];
49 cin.getline(strFirst,sizeof(strFirst));
50
51 cout<<"Enter your second(/detele) string:"<<endl;
52 char strSecond[StrMaxLength];
53 cin.getline(strSecond,sizeof(strSecond));
54
55 cout<<"the final string you want is:"<<endl;
56 DelChars(strFirst,strSecond);
57 cout<<strFirst<<endl;
58
59 return 0;
60 }
运行结果如下:
References:
程序员面试题精选100题:http://zhedahht.blog.163.com/blog/static/25411174200801931426484/
注:
1)本博客所有的代码环境编译均为win7+VC6。所有代码均经过博主上机调试。
2)博主python27对本博客文章享有版权,网络转载请注明出处http://www.cnblogs.com/python27/。对解题思路有任何建议,欢迎在评论中告知。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端