字符串旋转

描述:

  给定一个字符串,要求把字符串前面若干个字符移位到字符串的尾部。

思路与代码:

 1 //暴力法
 2 #include<stdio.h>
 3 #include<string.h>
 4 
 5 const int MAXN = 1e5;
 6 void move_one(char *s, int n)    //移动一个字符到尾部
 7 {
 8     char t = s[0];    //保存第一个字符
 9     for(int i = 1; i < n; i++)
10     {
11         s[i - 1] = s[i];
12     }
13     s[n - 1] = t;
14 }
15 void move(char *s, int n, int m)    //移动前m个字符到尾部
16 {
17     while(m--)
18     {
19         move_one(s, n);
20     }
21 }
22 int main()
23 {
24     char str[MAXN];
25     int m;
26     while(scanf("%s", str) != EOF)
27     {
28         getchar();
29         scanf("%d", &m);
30         int len = strlen(str);
31         move(str, len, m);
32         for(int i = 0; i < len; i++)
33             printf("%c", str[i]);
34         printf("\n");
35     }
36     return 0;
37 }

暴力法的复杂度:
  对一个长度为n的字符串来说,若需要移动m个字符到尾部,时间复杂度为O(m*n),空间复杂度为O(1),接下来来找找其他更好的方法来降低时间复杂度。

  举个例子,对于一个字符串abcdef,要将前三个移到尾部,可以先将原字符串划分成两部分,分别为字符串X:abc和字符串Y:def,然后将X反转变为cba,将Y反转变为fed,再将反转后的两字符串连接成cbafed,最后将连接后的再次反转即为defabc,得到移位后的字符串。所以找到了一种更高效的算法,将原字符串分成X和Y两部分,定义X^T为将字符串反转操作,则有(X^TY^T)^T=YX

 1 //三步反转法
 2 #include<stdio.h>
 3 #include<string.h>
 4 
 5 const int MAXN = 1e5;
 6 void reverse(char *s, int left, int right)  //反转字符串
 7 {
 8     while(left < right)
 9     {
10         char t = s[left];
11         s[left++] = s[right];
12         s[right--] = t;
13     }
14 }
15 void move(char *s, int n, int m)
16 {
17     m %= n; //若移动个数大于原长度,则和取余结果相等
18     reverse(s, 0, m - 1);   //前部分[0,...,m-1]
19     reverse(s, m, n - 1);   //后部分[m,...,n-1]
20     reverse(s, 0, n - 1);   //再整体反转
21 }
22 int main()
23 {
24     char str[MAXN];
25     int m;
26     while(scanf("%s", str) != EOF)
27     {
28         getchar();
29         scanf("%d", &m);
30         int len = strlen(str);
31         move(str, len, m);
32         for(int i = 0; i < len; i++)
33             printf("%c", str[i]);
34         printf("\n");
35     }
36     return 0;
37 }

三步反转法的复杂度:
  时间复杂度O(n),空间复杂度O(1)

 

posted @ 2018-11-05 18:02  Piccolo_Devil  阅读(221)  评论(0编辑  收藏  举报