题目:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.”。

分析:这是一道微软面试题。在微软的常见面试题中,与字符串相关的题目占了很大的一部分,因为写程序操作字符串能很好的反映我们的编程基本功。

要编程完成这道题要求的功能可能并不难。毕竟,这道题的基本思路就是在第一个字符串中拿到一个字符,在第二个字符串中查找一下,看它是不是在第二个字符串中。如果在的话,就从第一个字符串中删除。但如何能够把效率优化到让人满意的程度,却也不是一件容易的事情。也就是说,如何在第一个字符串中删除一个字符,以及如何在第二字符串中查找一个字符,都是需要一些小技巧的。

首先我们考虑如何在字符串中删除一个字符。由于字符串的内存分配方式是连续分配的。我们从字符串当中删除一个字符,需要把后面所有的字符往前移动一个字节的位置。但如果每次删除都需要移动字符串后面的字符的话,对于一个长度为n的字符串而言,删除一个字符的时间复杂度为O(n)。而对于本题而言,有可能要删除的字符的个数是n,因此该方法就删除而言的时间复杂度为O(n2)。

事实上,我们并不需要在每次删除一个字符的时候都去移动后面所有的字符。我们可以设想,当一个字符需要被删除的时候,我们把它所占的位置让它后面的字符来填补,也就相当于这个字符被删除了。在具体实现中,我们可以定义两个指针(pFast和pSlow),初始的时候都指向第一字符的起始位置。当pFast指向的字符是需要删除的字符,则pFast直接跳过,指向下一个字符。如果pFast指向的字符是不需要删除的字符,那么把pFast指向的字符赋值给pSlow指向的字符,并且pFast和pStart同时向后移动指向下一个字符。这样,前面被pFast跳过的字符相当于被删除了。用这种方法,整个删除在O(n)时间内就可以完成。

接下来我们考虑如何在一个字符串中查找一个字符。当然,最简单的办法就是从头到尾扫描整个字符串。显然,这种方法需要一个循环,对于一个长度为n的字符串,时间复杂度是O(n)。

由于字符的总数是有限的。对于八位的char型字符而言,总共只有28=256个字符。我们可以新建一个大小为256的数组,把所有元素都初始化为0。然后对于字符串中每一个字符,把它的ASCII码映射成索引,把数组中该索引对应的元素设为1。这个时候,要查找一个字符就变得很快了:根据这个字符的ASCII码,在数组中对应的下标找到该元素,如果为0,表示字符串中没有该字符,否则字符串中包含该字符。此时,查找一个字符的时间复杂度是O(1)。其实,这个数组就是一个hash表。这种思路的详细说明,详见本面试题系列的第13题。

基于上述分析,我们可以写出如下代码:

///
// Delete all characters in pStrDelete from pStrSource
///
void DeleteChars(char* pStrSource, const char* pStrDelete)
{if(NULL == pStrSource || NULL == pStrDelete)return;// Initialize an array, the index in this array is ASCII value.// All entries in the array, whose index is ASCII value of a// character in the pStrDelete, will be set as 1.// Otherwise, they will be set as 0.const unsigned int nTableSize = 256;int hashTable[nTableSize];memset(hashTable, 0, sizeof(hashTable));const char* pTemp = pStrDelete;while ('\0' != *pTemp){hashTable[*pTemp] = 1;++ pTemp;}char* pSlow = pStrSource;char* pFast = pStrSource;while ('\0' != *pFast){// if the character is in pStrDelete, move both pStart and// pEnd forward, and copy pEnd to pStart.// Otherwise, move only pEnd forward, and the character// pointed by pEnd is deletedif(1 != hashTable[*pFast]){*pSlow = *pFast;++ pSlow;}++pFast;}*pSlow = '\0';
}

本文已经收录到《剑指Offer——名企面试官精讲典型编程题》一书中,有改动。欢迎关注。

博主何海涛对本博客文章享有版权。网络转载请注明出处http://zhedahht.blog.163.com/。整理出版物请和作者联系。

程序员面试题精选100题(36)-在字符串中删除特定的字符[算法]相关推荐

  1. 程序员面试题精选100题(14)-圆圈中最后剩下的数字[算法]

    题目:n个数字(0,1,-,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字).当一个数字删除后,从被删除数字的下一个继续删除第m ...

  2. 程序员面试题精选100题

    程序员面试题精选100题(01)-把二元查找树转变成排序的双向链表 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向. 比如将二元查找树   ...

  3. 程序员面试题精选100题(09)-链表中倒数第k个结点[数据结构]

    题目:输入一个单向链表,输出该链表中倒数第k个结点.链表的倒数第0个结点为链表的尾指针.链表结点定义如下: struct ListNode {       int       m_nKey;      ...

  4. 程序员面试题精选100题(38)-输出1到最大的N位数[算法]

    题目:输入数字n,按顺序输出从1最大的n位10进制数.比如输入3,则输出1.2.3一直到最大的3位数即999. 分析:这是一道很有意思的题目.看起来很简单,其实里面却有不少的玄机. 应聘者在解决这个问 ...

  5. 程序员面试题精选100题(05)-查找最小的k个元素[算法]

    题目:输入n个整数,输出其中最小的k个. 例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4. 分析:这道题最简单的思路莫过于把输入的n个整数排序,这样排在最前面的k个 ...

  6. [程序员面试题精选100题]13.第一个只出现一次的字符

    [题目] 在一个字符串中找到第一个只出现一次的字符.如输入abaccdeff,则输出b. [分析] [代码] /********************************* * 日期:2013- ...

  7. 程序员面试题精选100题(51)-顺时针打印矩阵

    // 程序员面试题精选100题(51)-顺时针打印矩阵.cpp : 定义控制台应用程序的入口点. //#include "stdafx.h" #include <iostre ...

  8. 程序员面试题精选100题:求从1到n的正数中1出现的次数

    // 程序员面试题精选100题(25):求从1到n的正数中1出现的次数 // 如 f(253) = (2!=0) * 100 + 2 * f(99) + (5!=0) * 10 + 5 * f(9) ...

  9. 程序员面试题精选100题:41-50解题报告

    程序员面试题精选100题(41)-把数组排成最小的数[算法]   题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个.例如输入数组{32,  321},则输出这两个能 ...

最新文章

  1. Symbols in Interllij IDEA
  2. 移植uboot第一步:下载,编译,烧到板子上试验
  3. stm32-串口接受不定长数据方法(3种)
  4. linux笔记:shell基础-bash基本功能
  5. ecos(redboot)移植剖析
  6. 【C++ Primer | 15】面试问题
  7. 前端学习(3276):js中this的使用
  8. php yii 表单title,Yii2.0-ActiveForm表单结构自定义教程
  9. Nginx 0.8.x + PHP 5.2.13(FastCGI)搭建胜过Apache十倍的Web服务器(第6版)[原创]
  10. freebsd 运行linux,Freebsd 下运行 QQ For Linux 的方法
  11. Nightwish全部专辑320kbs全集下载
  12. 【antd-design-vue】a-table取消组件自带的暂无数据图片
  13. MATLAB函数随笔画图篇
  14. illumina不愧是二代测序无冕之王
  15. 未来十年最吃香专业大盘点,有你的吗?
  16. 苹果笔记本开不了机的解决措施有哪些
  17. dot.tk+namecheap.com搭建免费顶级域名+快速动态域名+Dns解析
  18. 工作十年之感悟 -- 兼谈生活与人生
  19. if,while选择结构和while,dowhile,for循环的使用
  20. 用Multisim仿真设计有源、无源,二阶、四阶滤波器

热门文章

  1. Learning to Rank 中Listwise关于ListNet算法讲授及实现
  2. 美国科技三巨头的财报为何集体爆表?原因在这里
  3. 易开发创始人潘俊勇:这些年我遇到的那些坑
  4. 白话Elasticsearch63-生产集群部署之硬件配置、jvm以及集群规划建议
  5. python字符串内建函数详解
  6. Android Studio报Element XXXX must be declared的解决方法
  7. html圆角兼容jq,IE兼容css3圆角的htc解决方法
  8. js 定时网页点击_JS的小乐趣:轻松完成打地鼠游戏
  9. 2020-12-07 Halcon初学者知识【2】打开图像和显示
  10. html中小于和大于怎么判断,html – CSS nth-child大于和小于