剑指offer--21题

时间:2023-01-26 14:05:51

#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&period; 调整数组顺序使奇数位于偶数前面

    剑指 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. html-fieldset线中嵌套字符

    <form> <fieldset> <legend>health information</legend> height: <input type ...

  2. 初识WebSocket协议

    1.什么是WebSocket协议 RFC6455文档的表述如下: The WebSocket Protocol enables two-way communication between a clie ...

  3. 打造自己的MyLifeOrganized 2(MLO2)云同步

    0x01 官方云同步,付费也很卡 MyLifeOrganized(MLO)是Windows平台下强大的GTD软件,PC版本和Android版本需要分别购买授权,云同步还要再买包月或包年服务真不便宜,关 ...

  4. MVC4中下拉菜单和单选框的简单设计方法

    举例一: @Html.LabelFor(model => model.Gender) @Html.DropDownListFor(model => model.Gender, new[] ...

  5. 阿里云实战之二&lpar;mysql&plus;phpmyadmin&rpar;

    前文安装好了空间的基本环境,本来运行在线代码编辑器不需要php+mysql的环境,不过我还是想在后续建设里面引入会员制度,这样php+mysql的环境就必不可少了. 一.Linux下MySQL忘记ro ...

  6. 2016022602 - redis安装和启动

    redis安装 我使用的是ubuntu15.1,打开终端,输入命令:sudo apt-get install redis-server 将会在本机安装上redis. 启动redis 启动redis命令 ...

  7. SpringBoot上传任意文件功能的实现

    一.pom文件依赖的添加 <dependencies> <dependency> <groupId>org.springframework.boot</gro ...

  8. csla框架&lowbar;&lowbar;使用Factory方式实现Csla&period;BusinessBase对象数据处理

    环境:.net4.6+csla4.6 实现:对象的数据库访问及数据库执行使用Factory方式进行封闭. 正文: 以前在使用csla框架完成业务对象的定义时所有的数据处理都在对象内部实现,也不能说不好 ...

  9. rt-thread平台 动态装载实现原理

    原理分析: a.在链接脚本link.lds里定义了专门存放动态符号表的段RTMSymTab. b.内核对外提供可延时绑定的接口在rtm.h中通过RTM_EXPORT将一对对符号+地址构成的表存放到RT ...

  10. &lbrack;CF1039D&rsqb;You Are Given a Tree

    [CF1039D]You Are Given a Tree 题目大意: 给定一棵\(n(n\le10^5)\)个节点的树.对于每一个正整数\(k(1\le k\le n)\),求最多能找出多少条包含\ ...