剑指offer答案全集Word格式文档下载.docx

上传人:b****2 文档编号:801394 上传时间:2023-04-29 格式:DOCX 页数:118 大小:91.78KB
下载 相关 举报
剑指offer答案全集Word格式文档下载.docx_第1页
第1页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第2页
第2页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第3页
第3页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第4页
第4页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第5页
第5页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第6页
第6页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第7页
第7页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第8页
第8页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第9页
第9页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第10页
第10页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第11页
第11页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第12页
第12页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第13页
第13页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第14页
第14页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第15页
第15页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第16页
第16页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第17页
第17页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第18页
第18页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第19页
第19页 / 共118页
剑指offer答案全集Word格式文档下载.docx_第20页
第20页 / 共118页
亲,该文档总共118页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

剑指offer答案全集Word格式文档下载.docx

《剑指offer答案全集Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《剑指offer答案全集Word格式文档下载.docx(118页珍藏版)》请在冰点文库上搜索。

剑指offer答案全集Word格式文档下载.docx

elsej--;

//向前一列

}

if(i==row||j<

0)returnfalse;

//没找到

returntrue;

//此句执行不到,只是为了编译没问题

}

分析:

时间复杂度O(m+n),m和n分别是行数和列数。

空间复杂度O

(1)。

思想是从右上角开始判断,每次判断可以排除一行或一列。

 

●替换空格

请实现一个函数,将一个字符串中的空格替换成“%20”。

例如,当字符串为WeAreHappy.则经过替换之后的字符串为We%20Are%20Happy。

//length为牛客系统规定字符串输出的最大长度,固定为一个常数

voidreplaceSpace(char*str,intlength){

if(NULL==str)return;

char*p=str;

intsize=0;

//记录str长度

intblankNum=0;

//记录空格个数

while(*p!

='

\0'

)//一直找到字符串尾部

if(*p=='

'

)blankNum++;

size++;

p++;

if(blankNum==0)return;

//没有空格,直接返回

intnewSize=size-blankNum+blankNum*3;

//计算新字符串大小

//if(newSize>

length)return;

char*end=str+newSize;

//

*end='

;

//最后一个字符置空

end--;

//往前一步

p=str+size-1;

//原字符串的最后一个字符处

while(p>

=str)

{//当前字符是空格,则替换

*end--='

0'

2'

%'

}

else

{//否则,不替换

*end--=*p;

p--;

//依次向前

}

时间复杂度O(N),N为字符串长度。

思想是先遍历一次得到字符串的长度和空格个数,计算出替换后的字符串长度,这样会在原字符串后面空出一段;

然后从后往前,碰到空格就替换。

鉴于义军的话:

就在牛客网上的那个编辑器里写代码,不要在VS里面写,因为VS有自动补全功能,而面试的时候是没有自动补全的。

所以从现在起,不在VS中写代码了,可能会在VS里查看有哪些成员函数。

2016.06.04

●从尾到头打印链表

输入一个链表,从尾到头打印链表每个节点的值。

/**

*structListNode{

*intval;

*structListNode*next;

*ListNode(intx):

*val(x),next(NULL){

*}

*};

*/

vector<

printListFromTailToHead(structListNode*head){

vec;

printTmp(head,vec);

returnvec;

voidprintTmp(ListNode*head,vector<

&

vec){

if(NULL==head)return;

printTmp(head->

next,vec);

vec.push_back(head->

val);

};

递归,时间复杂度O(N),N为链表长度。

因为要返回一个vector,所以必须另外写个函数,以便把vector作为参数。

●重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

*Definitionforbinarytree

*structTreeNode{

*intval;

*TreeNode*left;

*TreeNode*right;

*TreeNode(intx):

val(x),left(NULL),right(NULL){}

*};

*/

structTreeNode*reConstructBinaryTree(vector<

pre,vector<

in){

if(pre.size()==0||in.size()==0)returnNULL;

intsize=pre.size();

returnconstructTmp(pre,in,0,size-1,0,size-1);

TreeNode*constructTmp(vector<

pre,vector<

in,intprei,intprej,intini,intinj){

if(prei>

prej||ini>

inj)returnNULL;

TreeNode*node=newTreeNode(pre.at(prei));

inti=ini;

while(in.at(i)!

=pre.at(prei))i++;

intlen=i-ini;

node->

left=constructTmp(pre,in,prei+1,prei+len,ini,i-1);

right=constructTmp(pre,in,prei+len+1,prej,i+1,inj);

returnnode;

时间复杂度O(nlogn),n为节点个数。

递归的思想。

2016.06.05

●用两个栈实现队列

用两个栈来实现一个队列,完成队列的Push和Pop操作。

队列中的元素为int类型。

classSolution

{

voidpush(intnode){

stack1.push(node);

intpop(){

while(!

stack1.empty()){

stack2.push(stack1.top());

stack1.pop();

}

intret=stack2.top();

stack2.pop();

stack2.empty()){

stack1.push(stack2.top());

returnret;

private:

stack<

stack1;

stack2;

push时间复杂度为O

(1),pop时间复杂度为O(n)。

需要注意的是栈的操作push、pop(并不返回元素)、top、empty。

●旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。

输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。

例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。

NOTE:

给出的所有元素都大于0,若数组大小为0,请返回0。

intminNumberInRotateArray(vector<

rotateArray){

intsize=rotateArray.size();

if(size==0)return0;

intlow=0,high=size-1,mid;

while(low<

high){

if(rotateArray[low]<

rotateArray[high])break;

else{

mid=(low+high)/2;

if(rotateArray[mid]>

rotateArray[low])low=mid;

elseif(rotateArray[mid]<

rotateArray[mid-1]){

low=mid;

break;

}elsehigh=mid;

returnrotateArray[low];

线性扫描就不说了,此题的本意是利用二分查找,时间复杂度为O(logn)。

思想主要是根据arr[low]、arr[mid]、arr[high]的大小关系,判断最小元素在前半段还是后半段。

需要注意的是红色代码处,这种情况发生在:

5,6,1,2,3,4

此代码运行时间为20ms,感觉还是有点慢哎!

前面几题的运行时间都是0的。

下面用线性扫描试试,看看运行时间为多少:

intmin=rotateArray[0];

for(inti=1;

i<

size;

i++)

if(rotateArray[i]<

min)min=rotateArray[i];

returnmin;

结果时间也是20ms,呃呃呃。

不知什么情况了!

O(logn)和O(n)的运行时间是一样的。

●斐波那契数列

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。

intFibonacci(intn){

if(n==0)return0;

inttmp=1;

intret=0;

=n;

i++){

ret+=tmp;

tmp=ret-tmp;

1)拒绝用递归,因为会导致大量的重复计算。

2)初始条件为f(0)=0,f

(1)=1,f

(2)=1,递推公式f(n)=f(n-1)+f(n-2),n>

2

3)为了少用一个变量,采用了红色代码部分。

●跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级。

求该青蛙跳上一个n级的台阶总共有多少种跳法。

intjumpFloor(intn){

if(n<

=0)return0;

递推(跟斐波那契数列一样)。

设共有f(n)种方法,则有:

1)如果第一次跳1级台阶,那么接下来有f(n-1)种跳法;

2)如果第一次跳2级台阶,那么接下来有f(n-2)种跳法;

第一次要么跳1级,要么跳2级,所以只用上面两种情况,故总跳法数f(n)=f(n-1)+f(n-2)

初始条件:

f

(1)=1,f

(2)=2

●变态跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。

求该青蛙跳上一个n级的台阶总共有多少种跳法

intjumpFloorII(intn){

if(n<

tmp=ret;

跟上一题一样道理,递推。

递推公式:

f(n)=f(n-1)+f(n-2)+f(n-3)+…..+f

(1)

f(0)=1,f

(1)=1,f

(2)=2,f(3)=4…,这里加了一个f(0)=1,使得更好的服从递推。

●矩形覆盖

我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。

请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

intrectCover(intn){

intret=1;

for(inti=2;

tmp=ret-tmp;

递推公式f(n)=f(n-1)+f(n-2),f

(1)=1,f

(2)=2

●二进制中1的个数

输入一个整数,输出该数二进制表示中1的个数。

其中负数用补码表示。

intNumberOf1(intn){

intsum=0;

while(n){

sum++;

n&

=(n-1);

returnsum;

红色代码每执行一次,可以消去二进制中的一个1。

●数值的整数次方

给定一个double类型的浮点数base和int类型的整数exponent。

求base的exponent次方。

doublePower(doublebase,intexponent){

if((base<

=0.000001&

base>

=-0.000001)&

exponent<

0)return0.0;

if(exponent>

0)returnPowerTmp(base,exponent);

elsereturn1.0/PowerTmp(base,-exponent);

doublePowerTmp(doublebase,intex){

if(ex==0)return1.0;

if(ex==1)returnbase;

doubleret=Power(base,ex/2);

if(ex&

0x1)returnret*ret*base;

elsereturnret*ret;

时间复杂度为O(logn),n为指数。

1)首先判断base和exponent是否合法:

0的负数次幂不合法,0的0次幂默认为1.

2)考虑exponent正负,如果小于0,返回倒数;

3)如果exponent为奇数,则power(base,ex)=power(base,ex/2)*power(base,ex/2)*base;

如果exponent为偶数,则power(base,ex)=power(base,ex/2)*power(base,ex/2);

折半比循环快。

●调整数组顺序使奇数位于偶数前面

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

voidreOrderArray(vector<

array){

intsize=array.size();

if(size==0)return;

intodd=0,even=0;

//odd为奇数下标,even为第一个偶数下标

while(array[even]&

0x1)even++;

//找到第一个偶数

odd=even+1;

//从第一个偶数后面开始找到第一个奇数

while(odd<

size){

size&

!

(array[odd]&

0x1))odd++;

//找到下一个奇数

if(odd>

=size)break;

//如果没有奇数了,及时退出

//将[even,odd-1]之间的偶数向后移一位

inttmp=array[odd];

for(inti=odd;

i>

even;

i--)

array[i]=array[i-1];

array[even]=tmp;

//把奇数放到前面

even++;

odd++;

此题要是可以改变相对位置,则有时间复杂度为O(n)、空间复杂度为O

(1)的方法。

但是要保证相对位置不变,要么时间复杂度为O(n)、空间复杂度为O(n),要么时间复杂度为O(n*n)、空间复杂度为O

(1)。

本代码的时间复杂度为O(n*n),但运行时间为0ms。

那么此题的意义何在?

●链表中倒数第k个结点

输入一个链表,输出该链表中倒数第k个结点。

/*

structListNode{

intval;

structListNode*next;

ListNode(intx):

val(x),next(NULL){

ListNode*FindKthToTail(ListNode*pListHead,unsignedintk){

if(NULL==pListHead||k==0)returnNULL;

ListNode*p=pListHead;

inti=1;

while(i++<

k){

p=p->

next;

if(NULL==p)returnNULL;

//防止链表长度小于k

ListNode*node=pListHead;

while(p->

next){//p->

next为空时,p才指向最后一个节点

node=node->

时间复杂度O(n),n为节点个数。

思路:

先让一个指针走k-1步,然后另一个指针从头开始,两个指针同步向后走,当第一个指针走到最后一个节点时,第二个指针正好是倒数第k个节点。

注意一下几个地方:

1)链表为空;

2)k为0

3)链表长度小于k;

4)当第一个指针到达最后一个节点时,而不是指向空时,第二个指针才指向倒数第k个节点。

●反转链表

输入一个链表,反转链表后,输出链表的所有元素。

ListNode*ReverseList(ListNode*pHead){

if(NULL==pHead)returnNULL;

if(pHead->

next==NULL)returnpHead;

ListNode*node=pHead->

ListNode*head=ReverseList(node);

next=pHead;

pHead->

next=NULL;

returnhead;

递归实现。

精髓在于如何返回头结点(原来的尾节点):

一旦找到尾节点,就一直返回它,不让它参与任何操作。

下面是进一步简化的代码:

ListNode*head=ReverseList(pHead->

next);

next->

●合并两个排序的链表

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

ListNode*Merge(ListNode*pHead1,ListNode*pHead2){

if(NULL==pHead1)returnpHead2;

if(NULL==pHead2)returnpHead1;

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > IT计算机 > 电脑基础知识

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2