在网上一位博主的博客中看了有关左旋字符串的算法,原文地址http://blog.csdn.net/v_july_v/article/details/6322882,此博文给出了很多种解法,在这里我提出一些自己的观点。
题目描述:
定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。
如把字符串abcdef左旋转2位得到字符串cdefab。
请实现字符串左旋转的函数,要求对长度为n的字符串操作的时间复杂度为O(n),空间复杂度为O(1)。
大家都知道,现在用算法用的最多的地方就是ACM了,现在假如我们把这道题看成一道ACM的算法题,那么题目就变得很简单了。因为OJ对结果的判断只是进行字符串的匹配工作,假如题目的输入是abcdef,你最后只要输出cdefab就算你对了,你代码的执行过程发生了什么事就无所谓了。如果真的是这样的话,那这道题就很简单了。
我们只要用一个指针,开始定位到要旋转的位置的下一位,即上述字符串abcdef的c,然后做输出,最后把字符c改为'\0',输出整个字符串就行了(其实就是输出了旋转到后面的那部分),代码如下
#include <stdio.h> int main() { char str[100]; int rotate = 0; while(scanf("%s",str)) { scanf("%d",&rotate); char *p = str + rotate; printf("%s",p); *p = '\0'; printf("%s\n",str); } return 0; }
如果是右旋转,就把p从后面算回就可以了。
好了,现在我们不把它看成一个ACM的题目,如果题目的要求是改变字符串的内容,即把abcdef改成cdefab,我提出自己的观点,因为我在大三的时候做数据结构课程的作业就是这样做的。空间复杂度是O(1),时间复杂度为O(N)。
算法的基本思路是,把要旋转的字符串分成n组(n为左旋的位数),例如源字符串为abcdef,向左旋转2位,得到cdefab
a | b | c | d | e | f |
分成以下两组,然后分别对这两组进行循环移位就行了
a | c | e |
b | d | f |
变成以下两组:
c | e | a |
d | f | b |
合起来之后,就变成了旋转之后的字符串
c | d | e | f | a | b |
根据思路得到以下代码:
void Rotate(char str[], int n) { int len = strlen(str); n = n % len; for(int i = 0; i < n; ++i) { char c = str[i]; int j = 0; for(j = i; j < len; j += n) str[j] = str[j+n]; str[j-n] = c; } }
如有错误,欢迎各位指出。