字符串笔面试题

一、把一个字符串向左/右循环移位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]!='\0';i++) { temp[j][k]=s[i]; k++; if (s[i]==' ') //扫描字符串遇到空格,存到数组下一行,如果是开头的空格也一样处理,空间要求大  { j++; temp[j][k]='\0'; k=0; } } temp[j][k]=' ';//处理最后一个单词 k++; temp[j][k]='\0'; for (int i=j;i>=0;i--) { int k; for ( k=0;temp[i][k]!='\0';k++) { if (temp[i][k]==' ') //遇到空格跳出 break; else
           {
               ss[m]=temp[i][k]; m++; } } if (k>0) { ss[m]=' ';//不是开头结尾的加空格 m++; } } ss[m-1]='\0'; 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 != '\0') pEnd ++; pEnd--; // Reverse the whole sentence  Reverse(pBegin, pEnd); // Reverse every word in the sentence pBegin = pEnd = pData; while(*pBegin != '\0') { if(*pBegin == ' ') { pBegin ++; pEnd ++; } else if(*pEnd == ' ' || *pEnd == '\0') { Reverse(pBegin, --pEnd); pBegin = ++pEnd; } else
        {
            pEnd ++; } } return pData; } int main() { char pstr[]=" hello world! "; cout<<ReverseSentence(pstr);
}

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

你可能感兴趣的:(字符串,笔面试题)