• 字符串笔面试题


    一、把一个字符串向左/右循环移位n个。如abcdefghi,向左循环移位2个,结果为cdefghiab。

        这题的出现概率较大,难度较小

    1)如果没有空间的限制,那么第一个容易想到的解法是,申请一个strlen长的字符串数组,把字符串复制到这一数组,然后依照移位前后数组序号的关系,确定移位后的字符串。移位后的数字序号是未移位+n(移位距离),循环所以要%strlen

    char* rLeftfour(char * str,int n)
    {
        int slen=strlen(str);
        n%=slen;                      //循环左移位
        //n=slen-n%slen;          //循环右移位
        char *temp=new char[slen];
        for (int i=0;i<slen;i++)
            temp[i]=str[i];
        for (int j=0;j<slen;j++)
              str[j]=temp[(j+n)%slen];
        return str;
    }

    2)假设只能申请一个字节的额外空间,时间没有限制。那么可以对上述算法改进,每次只循环移动一位,总共循环n次。循环一位的时候,只需要保存第一个字符就行,后面的字符依次复制上来,然后把第一个字符复制到最后。

    char* rLefttwo(char * str,int n)
    {
        int slen=strlen(str);
        n%=slen;                   //循环左移位
        //n=slen-n%slen;          //循环右移位
        for (int i=0;i<n;i++)
        {   
            char temp=str[0];
            for (int j=0;j<slen-1;j++)
                str[j]=str[j+1];
            str[slen-1]=temp;    
    
        }
        return str;
    }

    3)在1)中申请空间可以缩小,只要保存移位的前n个字符即可,把后面依次复制到前面,最后把保存的字符复制到最后,

    char* rLeftone(char * str,int n)
    {
        int slen=strlen(str);
        n%=slen;               //循环左移位,等于数组长时相当于没有移位
        //n=slen-n%slen;          //循环右移位
        char *temp=new char[n];
        for (int i=0;i<n;i++)
            temp[i]=str[i];
        for (int j=n;j<slen;j++)
            str[j-n]=str[j];
        for (int k=0;k<n;k++)
            str[slen-n+k]=temp[k];
        return str;
    }

    4)来自于编程珠玑,思想是把原始字符串分成ab两部分,a是前i个元素,b是后n-i个元素,首先对a逆序,得到a-1b,然后对b逆序得到a-1b-1,然后对整体逆序得到(a-1b-1-1=ba。

    char* rLeftthree(char * str,int n)
    {
        int slen=strlen(str);
        n%=slen;               //循环左移位
        //n=slen-n%slen;          //循环右移位
        reverse(str,0,n-1);
        reverse(str,n,slen-1);
        reverse(str,0,slen-1);
        return str;
    }
    char* rLeftfour(char * str,int n)
    {
        int slen=strlen(str);
        n%=slen;               //循环左移位
        //n=slen-n%slen;          //循环右移位
        char *temp=new char[slen];
        for (int i=0;i<slen;i++)
            temp[i]=str[i];
        for (int j=0;j<slen;j++)
              str[j]=temp[(j+n)%slen];
        return str;
    }

    二、翻转字符串的词。如“the sky is blue”,翻转后为“blue is sky the”。要考虑字符串开头和结尾可能有空格。

    1)考虑额外的存储空间,保存字符串的每个单词于一个二维数组中,每行一个单词,开头结尾的空格也存储,然后从数组的尾扫描到头输出即可。

    #include <iostream>
    using namespace std;
    const int row=20;
    const int col=20;
    void reverse(char *&s)
    {
        char *ss=new char[row*col](); 
        char **temp=new char *[row];//新建二维数组存储字符串中单词
        int j=0,k=0,m=0;
        for (int i=0;i<row;i++)
        {
            temp[i]=new char[col]();
        }
        for (int i=0;s[i]!='';i++)
        {
            temp[j][k]=s[i];    
            k++;
            if (s[i]==' ')    //扫描字符串遇到空格,存到数组下一行,如果是开头的空格也一样处理,空间要求大
            {
                j++;
                temp[j][k]='';    
                k=0;
            }
            
        }
        temp[j][k]=' ';//处理最后一个单词
        k++;
        temp[j][k]='';
    
        for (int i=j;i>=0;i--)
        {
            int k;
           for ( k=0;temp[i][k]!='';k++)
           {
               if (temp[i][k]==' ')  //遇到空格跳出
                   break;
               else
               {
                   ss[m]=temp[i][k];
                   m++; 
               }
              
           } 
           if (k>0)
           {
               ss[m]=' ';//不是开头结尾的加空格
                m++;
           }
           
        }
        ss[m-1]='';
        cout<<ss<<endl; 
        s=ss;
    }
    int main()
    {
        char *s=new char[row*col];
        s=" hello world! we are one   ";
        reverse(s);
        cout<<s;
    }

       

     程序是将单词加空格后存成字符串,先分配内存后,扫描字符串,先存,不管是空格还是字符,若第二个是空格或者扫到空格的位置(因为是先存所以单词后都有空格),就到二维数组的下一行,直到字符串处理完毕。接着从二维数组的尾行开始,输出,若存的第一个是空格,忽略,然后把二维数组的单词输出到字符串中,每个单词间加空格。

    C++程序

    #include <iostream>
    #include <string>
    using namespace std;
    void reverseWords(string &s)
    {
        string rs;
        for (int i = s.length()-1; i >= 0; )
        {
            while (i >= 0 && s[i] == ' ') i--;
            if (i < 0) break;
            if (!rs.empty()) rs.push_back(' ');
            string t;
            while (i >= 0 && s[i] != ' ') t.push_back(s[i--]);
            reverse(t.begin(), t.end());
            //t.push_back(' ');
            rs.append(t);
        }
        s = rs;
    }
        int main()
        {
            string s=" hello world! ";
            
            reverseWords(s);
            cout<<s;
        }

          

          从后扫描,遇到空格则跳过,定义一个中间变量t来存单词,到空格时,把存的字符串翻转,成!dlrow,加到rs末,跳过空格,加空格在单词间。在最后一个单词时,i<0.不会加空格。

    2)利用字符串的翻转,先对整个字符串翻转,然后对字符串中的单词翻转。

    #include <iostream>
    using namespace std;
    void Reverse(char *pBegin,char  *pEnd)
    {
        if(pBegin == NULL || pEnd == NULL)
        return ;
    while(pBegin < pEnd)
    {
        char temp = *pBegin;
           *pBegin = *pEnd;
           *pEnd = temp;
           pBegin ++, pEnd --;
    }
    }
    char* ReverseSentence(char *pData)
    {
        if(pData == NULL)
            return NULL;
    
        char *pBegin = pData;
    
        char *pEnd = pData;
        while(*pEnd != '')
            pEnd ++;
        pEnd--;
    
        // Reverse the whole sentence
        Reverse(pBegin, pEnd);
    
        // Reverse every word in the sentence
        pBegin = pEnd = pData;
        while(*pBegin != '')
        {
            if(*pBegin == ' ')
            {
                pBegin ++;
                pEnd ++;
            }
            else if(*pEnd == ' ' || *pEnd == '')
            {
                Reverse(pBegin, --pEnd);
                pBegin = ++pEnd;
            }
            else
            {
                pEnd ++;
            }
        }
    
        return pData;
    }
    int main()
    {
        char pstr[]="   hello world!   ";
        cout<<ReverseSentence(pstr);
    }

         翻转整个字符串比较好理解,翻转词时,是定义了两个指针,一个指向词头,开始若是空格,两指针一起走,当不是空格时,end的指针向前走,走到空格后者尾时,翻转begin到end间字符,翻转后,要把begin指针移动到end位置,然后一起走,重复。类似上面,其实这题主要的难点在怎么处理那些头和尾的空格。上述代码没有处理空格。想处理空格应该也不难,在翻转后保存词,并加空格

  • 相关阅读:
    springboot系列九,springboot整合邮件服务、整合定时任务调度
    springboot系列八、springboot整合kafka
    springboot系列六、springboot配置错误页面及全局异常
    springboot系列五、springboot常用注解使用说明
    springboot系列四、配置模板引擎、配置热部署
    springboot系列三、springboot 单元测试、配置访问路径、多个配置文件和多环境配置,项目打包发布
    springboot系列二、springboot项目搭建
    springboot系列一、springboot产生背景及介绍
    kafka系列十、kafka常用管理命令
    Jmeter4.X
  • 原文地址:https://www.cnblogs.com/dawnminghuang/p/3942695.html
Copyright © 2020-2023  润新知