挑战面试编程:左移字符串
问题描述:
左移字符串:如有字符串“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.右移又该如何处理?
所有内容的目录