#include "stdafx.h"

#include<iostream>
using namespace std;

void LeftRotateString(char* str,int n);
void StringReverse(char* pStart, char* pEnd);

int main(int argc, char* argv[])
{
char str[]="abcdef";   //将"abcdef"拷贝到str[]中,str指向拷贝字符串的首址
int n=3;
LeftRotateString(str,n);
return 0;
}

/*void LeftRoundOper(char* str,int n)
{

int len=strlen(str);
char strtemp[100];
if(n<0 || n>len)
strtemp[0]='\0';

int i,j=0;
for(i=n; i<len; i++)
{
strtemp[j++]=str[i];
}
for(i=0; i<n; i++)
{
strtemp[j++]=str[i];
}
strtemp[j]='\0';

for(i=0; i<j; i++)
cout<<strtemp[i]<<' ';
cout<<endl;
}*/

/*接下来的一种思路可能要稍微麻烦一点。我们假设把字符串左旋转m位。
于是我们先把第0个字符保存起来,把第m个字符放到第0个的位置,在把第2m个字符放到第m个的位置…依次类推,
一直移动到最后一个可以移动字符,最后在把原来的第0个字符放到刚才移动的位置上。
接着把第1个字符保存起来,把第m+1个元素移动到第1个位置…重复前面处理第0个字符的步骤,
直到处理完前面的m个字符。*/

/*我们还是把字符串看成有两段组成的,记位XY。左旋转相当于要把字符串XY变成YX。
我们先在字符串上定义一种翻转的操作,就是翻转字符串中字符的先后顺序。把X翻转后记为XT。显然有(XT)T=X。

我们首先对X和Y两段分别进行翻转操作,这样就能得到XTYT。接着再对XTYT进行翻转操作,得到(XTYT)T=(YT)T(XT)T=YX。
正好是我们期待的结果。

分析到这里我们再回到原来的题目。
我们要做的仅仅是把字符串分成两段,第一段为前面m个字符,其余的字符分到第二段。
再定义一个翻转字符串的函数,按照前面的步骤翻转三次就行了。时间复杂度和空间复杂度都合乎要求。*/

void LeftRotateString(char* str,int n)
{
if(str!=NULL)
{
int len = strlen(str);
if(len>0 && n>0 && n<len)
{
StringReverse(str,str+n);
StringReverse(str+n,str+len);
StringReverse(str,str+len);
cout<<str<<endl;
}
}
}

void StringReverse(char* pStart, char* pEnd)
{
if(pStart!=NULL && pEnd!=NULL)
{
pEnd--;
while(pStart<pEnd)
{
char temp = *pStart;
*pStart = *pEnd;
*pEnd = temp;

pEnd--;
pStart++;
}
}
}

/*标准答案
#include "string.h"

///////////////////////////////////////////////////////////////////////
// Move the first n chars in a string to its end
///////////////////////////////////////////////////////////////////////
char* LeftRotateString(char* pStr, unsigned 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;

// reverse the first part of the string
ReverseString(pFirstStart, pFirstEnd);
// reverse the second part of the strint
ReverseString(pSecondStart, pSecondEnd);
// reverse the whole string
ReverseString(pFirstStart, pSecondEnd);
}
}

return pStr;
}

///////////////////////////////////////////////////////////////////////
// Reverse the string between pStart and pEnd
///////////////////////////////////////////////////////////////////////
void ReverseString(char* pStart, char* pEnd)
{
if(pStart != NULL && pEnd != NULL)
{
while(pStart <= pEnd)
{
char temp = *pStart;
*pStart = *pEnd;
*pEnd = temp;

pStart ++;
pEnd --;
}
}
}
*/

给自己做个备份,记录点点滴滴,看进步如何。。。

在验证各种方法时,遇到运行问题,也就是自己之前经常碰到的:在使用指针时,经常出现内存问题

比如该题中,

int main(int argc, char* argv[])
{
char str[]="abcdef";
int n=3;
LeftRotateString(str,n);
return 0;
}

第一种方法,使用char str[]="abcdef";和char* str="abcdef";均可

但标准答案只能使用char str[]="abcdef";

为什么?原因很简单,可惜我才明白。。

参考:http://bbs.csdn.net/topics/340111697

字符串“hello world”本身就是一个字符串常量指针,存储在静态存储区,而第一个指针p,无非就是一个地址的拷贝,也就是“hello world”地址的拷贝,此时的p指向静态存储区的"hello world"
实际就相当于 const char *p = "hello world"; 
======================================================================================
而对于p[]来说就不一样了,虽然"hello world"本身是常量,不过此时拷贝给p[]的不是地址,而是内容,也就是 “hello world”,也就是p本身拥有一个自己的hello world副本,而p此时代表的是自己副本的内存地址,而非静态区的"hello world"。由于p[]是一个局部变量,它的生存期只有在局部函数中,一旦结束调用,p就会消亡,p的内容就会被覆盖!因此结果是不确定的!

所以,"abcdef"是字符串常量,存储于静态存储区,直到程序结束才释放。

char* str="abcdef"将该静态存储区的地址赋予str,所以*str,str[i]均是取原字符串常量中的字符,切记:只能‘读’,不能‘写’,也就是不能修改值!

char str[]="abcdef"则将"abcdef"拷贝到动态存储区(栈)中,使之成为局部变量,此时的str将指向局部存储区的首址,*str,str[i]均取拷贝字符串的各值。因此能‘读’能‘写’。

进一步分析:自己所写的程序(最简单的),仅涉及到str[i],并开辟另外的存储空间,所以char* str="abcdef"与char str[]="abcdef"均可;

标准答案中涉及反转,也就是涉及到本地交换,所以只能char str[]="abcdef",不能修改原字符串常量。

剑指offer--21题的更多相关文章

  1. 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

    剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 Offer 21 这题的解法其实是考察快慢指针和头尾指针. package com.walegarrett.offer; /** * @Aut ...

  2. 剑指 offer 第一题: 二维数组中的查找

    打算写 图解剑指 offer 66 题 的系列文章,不知道大家有没有兴趣

  3. 剑指Offer编程题2——替换空格

    剑指Offer编程题2——替换空格 题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happ ...

  4. 剑指Offer编程题1——二维数组中的查找

    剑指Offer编程题1---------------二维数组中的查找 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完 ...

  5. 牛客网剑指offer刷题总结

    二维数组中的查找: 题目描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 两 ...

  6. 剑指offer刷题

    1.面试题43. 1-n整数中1出现的次数 输入一个整数 n ,求1-n这n个整数的十进制表示中1出现的次数. 例如,输入12,1-12这些整数中包含1 的数字有1.10.11和12,1一共出现了5次 ...

  7. 剑指offer编程题Java实现——面试题12相关题大数的加法、减法、乘法问题的实现

    用字符串或者数组表示大数是一种很简单有效的表示方式.在打印1到最大的n为数的问题上采用的是使用数组表示大数的方式.在相关题实现任意两个整数的加法.减法.乘法的实现中,采用字符串对大数进行表示,不过在具 ...

  8. 剑指offer编程题66道题 36-66

    36.两个链表的第一个公共节点 题目描述 输入两个链表,找出它们的第一个公共结点. 1.具有重合节点的两个链表是一个Y字性,用两个堆栈放这两个链表,从尾部开始遍历,直到遍历到最后一个重合节点. 这种算 ...

  9. 剑指offer刷题(Tree)

    开篇 二刷剑指offer了,本来用Tyora记的笔记,发现字数到四万了就变得好卡o(╥﹏╥)o,刚好开始写博客,就转过来吧,记下来子自己看.不废话,开刷... JZ26. 树的子结构 输入两棵二叉树A ...

  10. LeetCode剑指Offer刷题总结(一)

    LeetCode过程中值得反思的细节 以下题号均指LeetCode剑指offer题库中的题号 本文章将每周定期更新,当内容达到10题左右时将会开下一节. 二维数组越界问题04 public stati ...

随机推荐

  1. 索尼MT27i Android2.3.7 线刷Android4.04

    Author:KillerLegend From:http://www.cnblogs.com/killerlegend/p/3733150.html Date:2014.5.16 工具:Window ...

  2. for循环绑定事件,闭包思想!

    1.选项卡问题 总结:用alert()测试,是否得到对象. 2.闭包,解决作用域. <script> window.onload=function(){ var li=document.g ...

  3. 中兴软件编程规范C/C++

    Q/ZX 深圳市中兴通讯股份有限公司企业标准 (设计技术标准) Q/ZX 04.302.1–2003      软件编程规范C/C++                               20 ...

  4. 数据库事务故障恢复undo日志检查点

      checkpoint 检查点 checkpoint,即检查点.在undolog中写入检查点,表示在checkpoint前的事务都已经完成commit或者rollback 了,也就是检查点前面的事务 ...

  5. How to create QTP Shared Object Repository

    How to create QTP Shared Object Repository To create a shared object repository by performing follow ...

  6. poj 1789 Truck History

    题目连接 http://poj.org/problem?id=1789 Truck History Description Advanced Cargo Movement, Ltd. uses tru ...

  7. android 的生命周期自我理解

    android的active的生命周期,经过网站的blog学习,加上自己的理解总结如下: 第1种:全新的启动应用程序顺序 onCreate--->onStart---->onResume ...

  8. http://www.linuxso.com/linuxpeixun/10332.html

    http://blog.chinaunix.net/uid-134240-id-62371.html http://blog.chinaunix.net/uid-26495963-id-3279216 ...

  9. Swift Tips - Array 类型

    在开发中,数组这个概念我们应该很熟悉了,Objective-C 中为我们提供了 NSArray 作为数组的实现.大家应该对很熟悉了.而在 Swift 中,为我们提供了它自己对于数组的实现,也是这里我们 ...

  10. 使用 Swift 制作一个新闻通知中心插件(2)

    我们在第一部分的文章中详细讲解了创建一个通知中心插件的整体过程.我们成功的在通知中心里面显示了新闻列表.但是截止到目前,我们还不能从通知中心的列表中查看新闻的详细内容.在这次的教程中,我们就以上次的教 ...