字符串循环移位
题目示例: "abcdefgh" 循环右移3位得到 "defghabc"
解法一:消耗额外的3个空间,空间复杂度为O(n),当程序运行的空间比较苛刻的时候,不可取。时间复杂度为O(n)
1 int main(){ 2 char source[]="abcdefg"; 3 char *temp=new char[3]; 4 int i; 5 for(i=0;i<3;i++)temp[i]=source[i]; 6 for(i=0;i<(strlen(source)-3);i++)source[i]=source[i+3]; 7 for(i=0;i<3;i++)source[strlen(source)-3+i]=temp[i]; 8 cout<<source<<endl; 9 }
解法二:将每个元素直接移动到最后移动完字符串的相应的位置,所以需要移动n次。首先从x[0]开始,然后移动想想x[m]到x[0],x[2m]到x[i],依此类推,直到返回取x[0],如果从x[0]开始,没有能够移动所有元素,就从x[1]继续移动,直到所有元素都移动完为止。该算法的时间复杂度取决于外层循环执行的次数,当n,m的最大公倍数为1,则外层循环执行一次,如果最大公倍数为k,则执行k次。所以其时间复杂度几乎也为O(n)。解法2的空间复杂度较低,只占用一个字符的额外空间,为O(1)。
1 int main(){ 2 char source[]="abcdef"; 3 int n=strlen(source); 4 int m;cin>>m;//m为循环右移位数 5 m=m%n; 6 if(m==0)return 1; 7 8 int start_pos=0; 9 int changecount=0; 10 11 while(changecount<n){ 12 char temp=source[start_pos]; 13 int cur_pos=start_pos; 14 int next_pos=(cur_pos+m)%n; 15 while(next_pos!=start_pos){ 16 source[cur_pos]=source[next_pos]; 17 changecount++; 18 cur_pos=next_pos; 19 next_pos=(cur_pos+m)%n; 20 } 21 source[cur_pos]=temp; 22 changecount++; 23 start_pos++; 24 } 25 cout<<source<<endl; 26 }
解法三:观察移位后的字符串和原串的差别,字符串移n位相当于把前n位挪到了后面,而把后n位移到前面。设字符串长为AB,完成移位操作后新串为BA,用A'表示A的反序串,B'表示B的反序串,那么 BA = B''A'' =(A'B')'。
1 void reverse(char *a,int start,int end){ 2 while(start<end){ 3 int temp=a[start]; 4 a[start]=a[end]; 5 a[end]=temp; 6 start++; 7 end--; 8 } 9 } 10 11 int main(){ 12 char source[]="abcdef"; 13 int n=strlen(source); 14 int m;cin>>m;//m为循环右移位数 15 m=m%n; 16 if(m==0)return 1; 17 18 reverse(source,0,m-1); 19 reverse(source,m,n-1); 20 reverse(source,0,n-1); 21 cout<<source<<endl; 22 }
解法四:比较巧妙的做法就是对于字符串s,使newstring=ss,循环移n位的结果就等于newstring从下标n取strlen(s)位。如下题:
1 int main(){ 2 vector<string> vec; 3 int n;cin>>n; 4 string s; 5 for(int i=0;i<n*2;i++){cin>>s;vec.push_back(s);} 6 int j=1; 7 for(int i=1;i<vec.size();i=i+2){ 8 string temp=vec[i-1]+vec[i-1]; 9 int pos=temp.find(vec[i],0); 10 if(pos>3)cout<<"Case "<<j<<": "<<(3-pos)<<endl; 11 else 12 cout<<"Case "<<j<<": "<<pos<<endl; 13 j++; 14 } 15 16 }