剑指offer 阅读笔记 左旋转字符串
2016-07-06 18:31
281 查看
剑指offer 面试题 41_2 左旋转字符串字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部,请定义一个函数实现字符串左旋转操作的功能。比如输入字符串"abcdefg" 和2,该函数将返回旋转2位得到的结果“cdefgab”。 改天记录和书中不一样的解法。
书中思路是求字符串长度,然后求子串分割点。因为自己不擅长使用字符串函数,所以这里不求字符串长度,利用传入的n确定子串分割点。
该题的基础是有一个旋转函数,指定起始指针和结束指针,实现从起始到结束的旋转,比如对于"abcdefg" ,旋转之后返回“gfedcba”。 有了这个思路,对字符串实现左旋转,可以先旋转整个字符串,然后分别旋转子串,你如对于" abcdefg" ,整个旋转之后是“gfedcba”,然后我们再分别对“gfedc”和“ba”旋转,就得到“cdefgab"。
那么这里的重点就是找到分割点,比如整个字符串旋转之后,旋转前面一部分,我们让pEnd指向最后一个字符b,然后往前移动n位,比如此题2,位,就指向了g,所以此时传给reverse函数pBegin为c,pEnd指向g则实现了前面的反转,然后赋值pBegin
= ++pEnd,则pBegin就指向了a,然后让pEnd再次指向最后b,调用reverse函数就反转了ba。经过三次旋转之后字符串就为
“cdefgab",即完成了左旋转。当然要注意特殊情况的判断。代码如下:
char* LeftRotateString( char* pStr,int n)
{
if (pStr == NULL || n<= 0)
{
return pStr ;
}
//首先整个字符串翻转
char * pStart = pStr ;
char* pEnd = pStr ;
while( *pEnd != '\0')
{
pEnd ++ ;
}
pEnd -- ;
Reverse(pStart,pEnd) ;
////////////分别对两部分翻转,重要的是确定两个子串的开始结束指针
while(n > 0)
{
pEnd -- ;
n--;
}
///////////此时pend指向前面子串的尾部
Reverse(pStart ,pEnd);
if (*(pEnd +1 ) != '\0')
{
pStart = ++pEnd ;
}
while(*pEnd != '\0')
{
pEnd ++ ;
}
pEnd -- ;
Reverse(pStart ,pEnd);
return pStr ;
}
书中代码:
char* LeftRotateString(char* pStr, int n)
{
if(pStr != NULL)
{
int nLength = static_cast<int>(strlen(pStr));
if(nLength > 0 && n > 0 && n < nLength)
{
char* pFirstStart = pStr;
char* pFirstEnd = pStr + n - 1;
char* pSecondStart = pStr + n;
char* pSecondEnd = pStr + nLength - 1;
// 翻转字符串的前面n个字符
Reverse(pFirstStart, pFirstEnd);
// 翻转字符串的后面部分
Reverse(pSecondStart, pSecondEnd);
// 翻转整个字符串
Reverse(pFirstStart, pSecondEnd);
}
}
return pStr;
}书中代码虽然简洁,但是变量多。
reverse函数代码如下:
书中思路是求字符串长度,然后求子串分割点。因为自己不擅长使用字符串函数,所以这里不求字符串长度,利用传入的n确定子串分割点。
该题的基础是有一个旋转函数,指定起始指针和结束指针,实现从起始到结束的旋转,比如对于"abcdefg" ,旋转之后返回“gfedcba”。 有了这个思路,对字符串实现左旋转,可以先旋转整个字符串,然后分别旋转子串,你如对于" abcdefg" ,整个旋转之后是“gfedcba”,然后我们再分别对“gfedc”和“ba”旋转,就得到“cdefgab"。
那么这里的重点就是找到分割点,比如整个字符串旋转之后,旋转前面一部分,我们让pEnd指向最后一个字符b,然后往前移动n位,比如此题2,位,就指向了g,所以此时传给reverse函数pBegin为c,pEnd指向g则实现了前面的反转,然后赋值pBegin
= ++pEnd,则pBegin就指向了a,然后让pEnd再次指向最后b,调用reverse函数就反转了ba。经过三次旋转之后字符串就为
“cdefgab",即完成了左旋转。当然要注意特殊情况的判断。代码如下:
char* LeftRotateString( char* pStr,int n)
{
if (pStr == NULL || n<= 0)
{
return pStr ;
}
//首先整个字符串翻转
char * pStart = pStr ;
char* pEnd = pStr ;
while( *pEnd != '\0')
{
pEnd ++ ;
}
pEnd -- ;
Reverse(pStart,pEnd) ;
////////////分别对两部分翻转,重要的是确定两个子串的开始结束指针
while(n > 0)
{
pEnd -- ;
n--;
}
///////////此时pend指向前面子串的尾部
Reverse(pStart ,pEnd);
if (*(pEnd +1 ) != '\0')
{
pStart = ++pEnd ;
}
while(*pEnd != '\0')
{
pEnd ++ ;
}
pEnd -- ;
Reverse(pStart ,pEnd);
return pStr ;
}
书中代码:
char* LeftRotateString(char* pStr, int n)
{
if(pStr != NULL)
{
int nLength = static_cast<int>(strlen(pStr));
if(nLength > 0 && n > 0 && n < nLength)
{
char* pFirstStart = pStr;
char* pFirstEnd = pStr + n - 1;
char* pSecondStart = pStr + n;
char* pSecondEnd = pStr + nLength - 1;
// 翻转字符串的前面n个字符
Reverse(pFirstStart, pFirstEnd);
// 翻转字符串的后面部分
Reverse(pSecondStart, pSecondEnd);
// 翻转整个字符串
Reverse(pFirstStart, pSecondEnd);
}
}
return pStr;
}书中代码虽然简洁,但是变量多。
reverse函数代码如下:
void Reverse(char *pBegin, char *pEnd) { if(pBegin == NULL || pEnd == NULL) return; while(pBegin < pEnd) { char temp = *pBegin; *pBegin = *pEnd; *pEnd = temp; pBegin ++, pEnd --; } }这里只是关键函数代码,完整工程请私信哈。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- 数据库链接字符串查询网站
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Flex字符串比较 还有Flex字符串操作
- Ruby中创建字符串的一些技巧小结
- ASP下经常用的字符串等函数参考资料
- 将字符串小写转大写并延时输出的批处理代码
- 将字符串转换成System.Drawing.Color类型的方法
- Lua中调用C++函数示例
- Lua源码中字符串类型的实现
- Lua性能优化技巧(四):关于字符串
- Lua教程(一):在C++中嵌入Lua脚本
- 字符串聚合函数(去除重复值)
- Ruby中的字符串编写示例
- Lua教程(二):C++和Lua相互传递数据示例
- 总结的5个C#字符串操作方法分享
- sqlserver中求字符串中汉字的个数的sql语句
- sql server字符串非空判断实现方法