挑战面试编程:左移字符串
问题描述:
左移字符串:如有字符串“abcdefg”,可把它看作是一首尾相连的字符串,左移三个字符后,变为“defgabc”,请编程实现。
方法一:
利用额外的内存空间,实现中转。
步骤1:把“abc”存储到额外空间;
步骤2:把“defg”移动到字符串的首部。至此,“defg”到达最终位置。
步骤3:把“abc”strcat到“defg”的尾部。
char *leftMove(char *s, int n) { if (NULL == s || n <= 0 || n >= strlen(s)) return s; int L = strlen(s); char *tmp = malloc(sizeof(char)*L); strncpy(tmp, s, n); //步骤1 tmp[n] = 0; memmove(s, s + n, L - n + 1); //步骤2,移动的字节数是L-n+1(包含最后的结束符) strcat(s, tmp); //步骤3 free(tmp); return s; }
方法二:
比较巧妙,把s[0]存储到中间变量t,然后把s[n]存放到s[0],s[2n]存放到s[n],……直到s[0]存放到...。下标每次变化n,显然是需要对L求余的。
char *leftMove1(char *s, int n) { if (NULL == s || n <= 0 || n >= strlen(s)) return s; int i1, i2, L; char c; c = s[0]; L = strlen(s); i1 = n % L; i2 = 0; while (i1) { s[i2] = s[i1]; i2 = i1; i1 = (i1 + n) % L; } s[i2] = c; return s; }
每个元素都移动了一次,时间复杂度是O(n);只使用了一个中间变量,空间复杂度是O(1)。
方法三:
把问题抽象化,s=XY,X=“abc”,Y=“defg”。最后实现s=YX。
X'是X的逆置,Y'是Y的逆置。(X'Y')'=Y''X''=YX。
以上是类似数学上的一个推理过程。
char *reverse(char *s, int n) { if (NULL == s || n <= 0 || n > strlen(s)) return s; int left, right; char c; left = 0, right = n - 1; while (left < right) { c = s[left]; s[left] = s[right]; s[right] = c; left++; right--; } return s; } char *leftMove(char *s, int n) { if (NULL == s || n <= 0 || n >= strlen(s)) return s; int L = strlen(s); reverse(s, n); reverse(s + n, L - n); reverse(s, L); return s; }
思考题:
1.右移又该如何处理?
所有内容的目录