zoukankan      html  css  js  c++  java
  • 在字符串中删除特定的字

    以下分析文字转载自《程序员面试题精选100题(36)-在字符串中删除特定的字符》

    题目:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。

    例如,输入”They are students.””aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.”

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

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

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

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

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

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

    实现代码如下

     

    #include <stdio.h>
    #include
    <memory.h>
    /***********************************************************************************
    36
    输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。
    例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.”。
    **********************************************************************************
    */
    int delchar(char *src, char *dst);
    int main()
    {
    char src[] = "They are students.";
    char del[] = "aeiou";
    delchar(src, del);
    printf(
    "Output : %s\n",src);
    return 0;
    }

    int delchar(char *src, char *dst)
    {
    char *begin = src;
    char *end = src;
    char hashtable[256];
    int i = 0;
    memset(hashtable,
    0,sizeof(hashtable));
    while(*dst)
    ++hashtable[*dst++];
    while(*end)
    {
    if(!hashtable[*end])//del character not detected
    {
    *begin = *end ;
    ++begin;
    }
    ++end;

    }

    *begin= '\0';
    }

    借鉴的地方

    1)hash的策略,特别是在数据有上下限的时候,可以考虑将其转换为hash——至于如何映射也是需要注意的地方。

        此处数组中的元素值即为其hash到数组中的值,支持[]访问。其它地方或许没有这样的恰到好处。

    2)在实现的时候,要转换思路——所谓的删除操作就是覆盖元素的值,考虑清楚了这点的话,其它应该就不是难事。用两个指针分别表示新数组的数据和原数组的数据。遍历来实现值的覆盖。

  • 相关阅读:
    java笔记使用线程池优化多线程编程
    java笔记查看和修改线程名称
    java笔记查看和修改线程的优先级
    java笔记策略模式和简单工厂模式
    java笔记用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程
    java笔记枚举总结与详解
    java笔记关于克隆技术
    java笔记反射机制之基础总结与详解
    java笔记使用事件分配线程更新Swing控件
    java笔记关于int和byte[]的转换
  • 原文地址:https://www.cnblogs.com/westfly/p/2009499.html
Copyright © 2011-2022 走看看