剑指Offer面试题1
2016-06-02 13:08
399 查看
面试题1:
题目描述:如下为类型CMyString的声明,请为该类型添加赋值运算符函数。
classCMyString
{
public:
CMyString(char*pData=NULL);
CMyString(constCMyString&str);
~CMyString(void);
private:
char*m_pData;
};
思路: 现代写法,传一个临时参数tmp,然后将tmp的m_pData值与this指针指向的值进行交换,就实现了运算符的重载。
注:tmp出了作用域会自动调用析构函数释放,所以当tmp区域与this指向的为同一区域时,tmp释放,则this指针
指向的区域也释放了,就会出现问题,所以需要加上条件(this!=&str)。
代码:CMyString&CMyString::operator=(constCMyString&str) { if(this!=&str) { CMyStringtemp(str); char*data=temp.m_pData; temp.m_pData=this->m_pData; this->m_pData=data; } return*this; }
面试题3:
题目描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
输入描述:
array:待查找的二维数组
target:查找的数字
输出描述:
查找到返回true,查找不到返回false
思路:从二维数组的左下角开始找,若当前位置比target小,则向右移;反之,向上移动。
代码:classSolution
{
public:
boolFind(vector<vector<int>>array,inttarget)
{
introw=array.size();//行
intcol=array[0].size();//列
intx=row-1;//横坐标
inty=0;//纵坐标
while(x>=0&&y<col)
{
if(array[x][y]>target)//当前位置值>target,上移
x--;
elseif(array[x][y]<target)//当前位置值<target,右移
y++;
else
returntrue;
}
returnfalse;
}
};
面试题4:
题目描述:请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为WeAreHappy.则经过替换之后的字符串为We%20Are%20Happy。
思路:先计算空格个数,str原长及新长度,然后从后向前拷贝,避免内存覆盖
代码://假定length为系统规定字符串输出的最大长度,固定为一个常数
classSolution
{
public:
voidreplaceSpace(char*str,intlength)
{
if(str==NULL||length<0)//当str为空或最大长度非法,则返回
{
return;
}
intlen=0;//str的长度
intblank=0;//空格的个数
inti=0;
while(str[i]!='\0')
{
if(str[i++]=='')
blank++;
len++;
}
intnewlen=len+2*blank;//str替换后新的长度
if(newlen>length)//新长度<系统分配的最大长度时,返回
return;
//str的替换过程,从后向前拷贝
while(len>=0&&newlen>len)
{
if(str[len]!='')
str[newlen--]=str[len];
else
{
str[newlen--]='0';
str[newlen--]='2';
str[newlen--]='%';
}
len--;
}
}
};
面试题5:
题目描述:输入一个链表,从尾到头打印链表每个节点的值。
输入描述:
输入为链表的表头
输出描述:
输出为需要打印的“新链表”的表头
思路:递归,直至找到最后一个节点,进行打印。
代码:/**
*structListNode{
*intval;
*structListNode*next;
*ListNode(intx):
*val(x),next(NULL){
*}
*};
*/
classSolution{
public:
vector<int>printListFromTailToHead(structListNode*head)
{
vector<int>tail;
if(head!=NULL)
{
if(head->next!=NULL)
tail=printListFromTailToHead(head->next);
tail.push_back(head->val);
}
returntail;
}
};
面试题6:
题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:前序遍历的第一个节点为根节点root,再根据中序遍历的结果,查找到中序遍历结果中与root值相等的位置index,
则该值左边的为左子树的节点,右边的为右子树的节点。然后以左、右子树为子问题,递归调用函数重建子树。
代码:/**
*Definitionforbinarytree
*structTreeNode{
*intval;
*TreeNode*left;
*TreeNode*right;
*TreeNode(intx):val(x),left(NULL),right(NULL){}
*};
*/
classSolution{
public:
structTreeNode*reConstructBinaryTree(vector<int>pre,vector<int>in)
{
intSize=in.size();//遍历这棵树的节点数
if(Size==0)//树为空
returnNULL;
vector<int>preLeft,preRight,inLeft,inRight;
intval=pre[0];//根节点的值(前序遍历的第一个值)
TreeNode*node=newTreeNode(val);//构建根节点
intindex=0;
for(index=0;index<Size;++index)
{
if(in[index]==val)//在前序遍历结果中查找根节点值的位置
break;
}
for(inti=0;i<Size;++i)
{
if(i<index)//在中序遍历结果中,在根节点前的值均为二叉树的左子树的值
{
//构建左子树
inLeft.push_back(in[i]);
preLeft.push_back(pre[i+1]);
}
elseif(i>index)
{
//构建右子树
inRight.push_back(in[i]);//Constructtherightpreandin
preRight.push_back(pre[i]);
}
}
//分为子问题,递归调用
node->left=reConstructBinaryTree(preLeft,inLeft);
node->right=reConstructBinaryTree(preRight,inRight);
returnnode;
}
};
面试题7:
题目描述:用两个栈来实现一个队列,完成队列的Push和Pop操作。队列中的元素为int类型。
思路: 两个栈实现一个队列,记两个栈分别为stack1、stack2。入队列操作,即为入栈stack1操作;
而出队列可先将stack1中的数据全部push到stack2中,两次先进后出,使得stack2中数据顺
序就是队列先进先出的顺序,然后再将stack2的top数据pop即可。
但须注意的是:将stack1中数据push到stack2之前,徐判断stack2是否为空:
1)若为空,则将stack1中数据全部push进来后在pop它的top数据。
2)若stack2中原本就有数据,则需先将stack2中原有的数据先pop
代码:
classSolution
{
public:
voidpush(intnode)//直接将数据入stack1,先进后出一次
{
stack1.push(node);
}
intpop()
{
if(stack2.empty())//若stack2为空,将stack1的数据全push进stack2中,先进后出二次(stcak2中的数据顺序为队列中的数据顺序)
{
while(!stack1.empty())
{
stack2.push(stack1.top());
stack1.pop();
}
}
inttop=stack2.top();//保存stack2的顶部数据
stack2.pop();//将stack2中的顶部元素pop出去
returntop;
}
private:
stack<int>stack1;
stack<int>stack2;
};