左旋字符串是许多公司面试官喜欢问到的问题,那么这片博文就是要讲一下左旋字符串的实现以及《剑指offer》里面是怎样解决这个问题。
一.先看看一道面试题
eg:输入一个英语句子,翻转句子中单词的顺序,但单词内字符额顺序不变。为了简单起见,标点符号和普通字母一样处理。例如输入字符串“i am a student.”,则输出“student. a am i”。
或许许多同学都见过这道题,应该怎么实现这个功能呢?
1.
1).首先翻转整个字符串。产生的结果就是“.tneduts a ma i”。
2).翻转每一个单词。产生结果为“student. a am i”。
2.思路理清楚了,怎么写代码呢?
1).首先实现一个字符串翻转函数。
实现代码:
void reverse(char *left, char *right)
{
assert(left);
assert(right);
while (left < right)
{
char tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
2).接下来就要实现单词内字符的翻转。这时就要考虑传入的是一个单词的条件。不难发现空格可以作为很好的判断条件。难么我们再来实现一下。
void reverse_arr(char *arr, int len)
{
assert(arr);
char *pleft = arr;
char *pend = arr + len - 1;
reverse(pleft, pend);
while (*arr != '\0')
{
char *pcur = arr;
while ((*arr != '\0') && (*arr) != ' ')
{
arr++;
}
reverse(pcur, arr - 1);
if (*arr == ' ')
{
arr++;
}
}
}
这个函数就这样实现了。那么,和我们今天要说的左旋字符串有什么关系呢?不妨让我们在思考左旋字符串的实现。
二.左旋字符串的实现
1.有了上面的问题作为铺垫,应该并不难想到左旋字符串的实现也可以依葫芦画瓢。
2.给一个左旋字符串的题目吧,这样比较利于我们思考。
eg:字就自己符串的左旋操作是把字符串前面的若干个字符转移到字符串的尾部。比如,输入字符串“abcdefg”和数字2,该函数将返回左旋转2位i得到的结果“cdefgab”。
1).这道题目的字符串操作数是2,那么我们是不是可以考虑将前两位字符串翻转,既ab翻转得到ba? 然后将字符串后面的字符,再进行翻转,既cdefg得到gfedc。那么我们的字符串变成了“bagfedc”,然后将整个字符串反转是不是就可以得到我们想要的左旋字符串?让我们一起来实现一下吧。
2).同理需要一个实现字符串翻转的函数。和上面的代码一样,我就不再重复。
3).那么剩下来就是调用字符串翻转函数的问题,说直白一点就是传参的问题。看看我的实现代码。
void left_move(char *arr, int len, int k)
{
assert(arr);
if(len>0 && n>0 && k<len)
{
reverse(arr, arr + k - 1);
reverse(arr + k, arr + len - 1);
reverse(arr, arr + len - 1);
}
}
4).需要解释上面函数的参数。首先字符指针,其次是字符串长度(如果面试官不让你使用库函数那么就自己实现一个这样的函数),最后是左旋操作数。
三.总结一下
1.通过第一个例子,我们得到一个经验,既字符串在旋转的时每个字符移动的规律,从而受到启发。在实现左旋字符串中我们运用我们学到的知识很好的解决了问题。
2.该函数在完成过程中需要考虑:
1).输入空指针NULL是程序会崩溃。
2).内存访问越界问题。(n<0 && n>len)
四。我在最初实现左旋字符串的代码
#include<stdio.h>
void left_move(char *str, int k)
{
int i = 0;
for (i = 0; i < k; i++)
{
char tmp = *str;
int j = 0;
while (*(str+1+j))
{
*(str+j) = *(str + 1 + j);
j++;
}
*(str+j) = tmp;
}
}
int main()
{
char arr[] = "abcdef";
left_move(arr, 2);
printf("%s",arr);
system("pause");
return 0;
}
#include<stdio.h>
#include<assert.h>
void left_move(char *det, char *src, int k)
{
assert(det);
assert(src);
int i = 0;
int j = 0;
int len = strlen(src);
j = len - k;
for (i = 0; i < k; i++)
{
det[j] = src[i];
j++;
}
for (j = 0,i=k; i < len; i++)
{
det[j] = src[i];
j++;
}
det[len] = '\0';
}
int main()
{
char arr2[128]= "abcdef";
char arr1[128];
left_move(arr1, arr2, 2);
printf("%s", arr1);
system("pause");
return 0;
}
以上就是本人在学习过程中的一些经验总结。当然,本人能力有限,难免会有纰漏,希望大家可以指正。
转载于:https://blog.51cto.com/10799170/1715484