剑指offer习题集1
1.打印二叉树
程序很简单,但是其中犯了一个小错误,死活找不到,写代码要注意啊
这里左右子树,要注意是node->left,结果写成root->left
vector<int> PrintFromTopToBottom(TreeNode *root) {
vector<int> res;
if (NULL == root)
return res;
TreeNode* node;
deque<TreeNode*> tmp;
tmp.push_back(root);
while (tmp.size()) {
node = tmp.front();
res.push_back(node->val);
tmp.pop_front();
if (node->left)
tmp.push_back(node->left);
if (node->right)
tmp.push_back(node->right);
}
return res;
}
2.求1+2+...+n
class A{
public:
A(){
++n;sum+=n;
}
static int getsum(){
return sum;
}
static void reset(){
n=;sum=;
}
~A(){}
private:
static int n;
static int sum;
};
int A::n=;
int A::sum=;
class Solution {
public:
int Sum_Solution(int n) {
A::reset(); //必不可少,测试集会重复运行
A* tmp=new A[n];
delete[] tmp;
return A::getsum();
}
};
3.二叉树镜像
class Solution {
public:
void Mirror(TreeNode *pRoot) {
if(NULL==pRoot||(NULL==pRoot->left&&NULL==pRoot->right))
return;
mirrorset(pRoot);
}
void mirrorset(TreeNode* root){
if(NULL==root||(NULL==root->left&&NULL==root->right))
return;
TreeNode *tmp=root->left;
root->left=root->right;
root->right=tmp;
if(root->left)
mirrorset(root->left);
if(root->right)
mirrorset(root->right);
}
};
4.合并两个排序的链表
剑指offer书上用的是递归,感觉不必那么麻烦,用一个循环就可以解决。
ListNode1* Merge(ListNode1* pHead1, ListNode1* pHead2)
{
//避免空指针
if (NULL == pHead1 || NULL == pHead2)
return NULL == pHead1 ? pHead2 : pHead1; //选取两个链表中的最小值作为链表头
bool sign[] = { false };
ListNode1 *p1 = pHead1, *p2 = pHead2, *p3, *res;
if (p1->val < p2->val) {
res = p1;p3 = res;p1 = p1->next;sign[] = true;
}
else {
res = p2;p3 = res;p2 = p2->next;sign[] = true;
} while (p1&&p2) {
if (p1->val < p2->val) {
if (sign[]) {
p1 = p1->next;
p3 = p3->next;
}
else {
p3->next = p1;
p1 = p1->next;
p3 = p3->next;
}
sign[] = true;sign[] = false;
}
else {
if (sign[]) {
p2 = p2->next;
p3 = p3->next;
}
else {
p3->next = p2;
p2 = p2->next;
p3 = p3->next;
}
sign[] = false;sign[] = true;
}
} if (p1) {
p3->next = p1;
}
else if (p2) {
p3->next = p2;
} return res;
}
5.复杂链表的复制
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if(NULL==pHead)
return NULL; //复制链表节点,并嵌入原链表
RandomListNode *p1=pHead,*p2=pHead,*res;
while(p1){
RandomListNode *temp=new RandomListNode(p1->label);
temp->next=p1->next;
p1->next=temp; if(NULL==temp->next)
break;
else p1=temp->next;
} //复制随机指针
p1=pHead;
while(p1){
p2=p1->random;
p1=p1->next;
p1->random=p2;
p1=p1->next;
} //拆分链表
p1=pHead;p2=p1->next;res=p2;
while(p1&&NULL!=p2->next){
p1->next=p2->next;
p1=p1->next;
p2->next=p1->next;
p2=p2->next;
}
p1->next=NULL; return res;
}
};
6.顺时针打印矩阵
void print(const vector<vector<int>>& matrix, const int& len1, const int& len2, const int& n, vector<int>& res) {
int i, endx = len1 - - n, endy = len2 - - n;
//从左至右存储
for (i = n;i <= endy;++i) {
res.push_back(matrix[n][i]);
}
//从上至下存储
if (n < endx) {
for (i = n + ;i <= endx;++i)
res.push_back(matrix[i][endy]);
}
//从右至左打印
if (n < endx&&n < endy) {
for (i = endy - ;i >= n;--i)
res.push_back(matrix[endx][i]);
}
//从下至上打印
if (n < endx - && n < endy) {
for (i = endx - ;i >= n + ;--i)
res.push_back(matrix[i][n]);
}
}
vector<int> printMatrix(vector<vector<int>>& matrix) {
vector<int> res;
int len1 = matrix.size(), len2, n = ;
if ( == len1) {
return res;
}
else if ( == len1) {
return matrix[];
}
else {
len2 = matrix[].size();
}
while ( * n < len1 && * n < len2) {
print(matrix, len1, len2, n, res);
++n;
}
return res;
}
在VS上写程序真的是很简单,各种智能提示,在其他IDE上写程序,就得时刻注意。。。结果还是不容易找到错误
7.不能用加减乘除做加法
class Solution {
public:
int Add(int num1, int num2)
{
int sum1,sum2;
do{
sum1=num1^num2;
sum2=(num1&num2)<<;
num1=sum1;
num2=sum2;
}while(num2!=);
return sum1;
}
};
日了够了,就不能一遍通过,左移右移竟然能犯错误。
8.翻转字符串
注意j值的变化,机试时不带调试,实在是无语啊
class Solution {
public:
string ReverseSentence(string str) {
int len=str.length();
if(len<=) return str;
int i,j,left,right;
//首先翻转整条语句
reverse(str,,len-);
//逐个翻转单词
left=;right=;
for(i=;i<len;i++){
if(str[i]!=' '){
left=i;
for(j=i+;j<=len;j++){
if(str[j]==' '||str[j]=='\0'){
right=j-;
break;
}
}
reverse(str,left,right);
i=j; //从当前为空格字符运行
}
}
return str;
}
private:
void reverse(string& str,int left,int right){
if(left<||right<||(right-left)<=)
return;
char temp;
while(left<right){
temp=str[left];
str[left]=str[right];
str[right]=temp;
++left;
--right;
}
}
};
9.数组在排序数组中出现的次数
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
bool sign=false;
int len=data.size();
if(==len) return ;
int left=,right=len-,mid;
//通过二分查找法先缩小搜索范围
while(left<=right){ //注意二分查找法此处是等号,否则应对只有一个元素,岂不是呵呵了
mid=(left+right)>>;
if(data[mid]==k){
sign=true;break;
}else if(data[mid]<k){
left=mid+;
}else{
right=mid-;
}
}
if(!sign) return ; //确保数组中包含此数据
return getlastk(data,len,k,mid,right)-getfirstk(data,k,left,mid)+;
}
int getfirstk(vector<int>& data,const int& k,int left,int right){
int mid=(left+right)>>;
int midval=data[mid];
if(midval==k){
if((mid>&&data[mid-]!=k)||mid==){
return mid;
}else
right=mid-;
}else if(midval<k){
left=mid+;
}else{
right=mid-;
}
return getfirstk(data,k,left,right);
}
int getlastk(vector<int>& data,const int& len,const int& k,int left,int right){
int mid=(left+right)>>;
int midval=data[mid];
if(midval==k){
if((mid<len-&&data[mid+]!=k)||mid==len-){
return mid;
}else{
left=mid+;
}
}else if(midval<k){
left=mid+;
}else{
right=mid-;
}
return getlastk(data,len,k,left,right);
}
};
10.二叉树的下一节点(看着答案做的,还需重新做)
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
if(NULL==pNode)
return NULL;
TreeLinkNode* pnext=NULL;
if(pNode->right!=NULL){
TreeLinkNode *right=pNode->right;
while(right->left){
right=right->left;
}
pnext=right;
}else if(pNode->next){
TreeLinkNode *curr=pNode;
TreeLinkNode *parent=curr->next;
while(parent!=NULL&&curr==parent->right){
curr=parent;
parent=parent->next;
}
pnext=parent;
}else{
//父节点无右子树
}
return pnext;
}
};
11.按行打印二叉树
运行一直出错,还是找不到错误,后续才发现少了return res;
在线测试也不会提醒这个错误的,简直对自己无语了啊。
vector<vector<int> > Print_test(BinaryTreeNode* pRoot) {
vector<vector<int>> res;
if (NULL == pRoot)
return res;
int print = , nextlevel = ;
BinaryTreeNode* temp;
std::queue<BinaryTreeNode*> nodes;
std::vector<int> tval;
nodes.push(pRoot);
while (nodes.size()) {
temp = nodes.front();
tval.push_back(temp->m_nValue);
if (temp->m_pLeft) {
nodes.push(temp->m_pLeft); ++nextlevel;
}
if (temp->m_pRight) {
nodes.push(temp->m_pRight); ++nextlevel;
}
nodes.pop();
--print;
if (!print) {
//通过队列记录数值,并在读取完一层之后进行清空
vector<int> val;
for (int i = ;i<tval.size();++i) {
val.push_back(tval[i]);
}
tval.clear();
res.push_back(val);
print = nextlevel;
nextlevel = ;
}
}
return res;
}
以后一定先写return res;
还有就是声明指针的时候一定记住初始化为NULL。
12.找最小的k个数
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
int len=input.size();
if(len<k){
vector<int> res;return res;
}else if(len==k){
return input;
}
QuickSort(input);
vector<int> data;
for(int i=;i<k;++i){
data.push_back(input[i]);
}
return data;
}
void Qsort(vector<int>& data,int left,int right)
{
if (left < right)
{
//此步保证data[pivot]大于左边的元素小于右边的元素,arry[pivot]被正确安排
int pivot = partition(data, left, right);
Qsort(data, left, pivot - );
Qsort(data, pivot + , right);
}
}
void QuickSort(vector<int>&data)
{
Qsort(data, , data.size() - );
}
void swap(int&a, int&b) {
int t = a;a = b;b = t;
}
int partition(vector<int>& data,const int& start,const int& end){
int left=start,right=end;
int pivot=data[left];
while(left<right){
while(left<right&&data[right]>=pivot)
--right;
swap(data[left],data[right]);
while(left<right&&data[left]<=pivot)
++left;
swap(data[left],data[right]);
}
return left;
}
};
快排必须将第一个数值作为基准,当然,你要想选取中间数值,可以将中间数值与第一个数值进行交换。
13.反转链表
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(NULL==pHead||NULL==pHead->next)
return pHead;
ListNode* reversehead=NULL;
ListNode* prenode=NULL;
ListNode* currnode=pHead;
ListNode* nextnode=NULL;
while(currnode){
nextnode=currnode->next;
if(NULL==nextnode){
reversehead=currnode;
}
currnode->next=prenode;
prenode=currnode;
currnode=nextnode;
}
return reversehead;
}
};
14.调整数组顺序,奇数位于偶数之前
class Solution {
public:
void swap(int& a,int& b){
int t=a;a=b;b=t;
}
void reOrderArray(vector<int> &array) {
int len=array.size();
if(==len||==len)
return;
int left=,right=len-;
while(left<right){
while(left<right&&array[left]%==)
++left;
while(left<right&&array[right]%==)
--right;
if(left<right)
swap(array[left],array[right]);
}
}
};
不过此方法会改变奇数与奇数,偶数与偶数之间的相对关系。
15.数组中出现次数超过一半的数字
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int len=numbers.size();
if(==len)
return ;
else if(==len) return numbers[];
else if(len<=) return numbers[];
int index,start=,end=len-;
int mid=len>>;
index=partition(numbers,start,end);
while(index!=mid){
if(index>mid){
end=index-;
index=partition(numbers,start,end);
}else{
start=index+;
index=partition(numbers,start,end);
}
}
if(judge(numbers,numbers[index],len)){
return numbers[index];
}else return ;
}
private:
void swap(int& a,int& b){
int t=a;a=b;b=t;
}
//此处因为调用函数确保了鲁棒性,故此处不添加相关检验
int partition(vector<int>& num,const int& start,const int& end){
int left=start,right=end,pivot=num[start];
while(left<right){
while(left<right&&num[right]>=pivot)
--right;
swap(num[left],num[right]);
while(left<right&&num[left]<=pivot)
++left;
swap(num[left],num[right]);
}
return left;
}
bool judge(vector<int>& num,const int&k,const int& len){
int i,n=;
for(i=;i<len;i++){
if(num[i]==k){
++n;
}
}
return (n>len/)?true:false;
}
};
此题还是犯了错误,一个是没有判断中位数究竟是不是在数组中超过一半,即先天条件满不满足。
另外一个就是数组维数为1的时候,应该返回此数字,因为明显满足条件。。。
16.二维数组的寻找
class Solution {
public:
bool Find(vector<vector<int> > array,int target) {
int i,j,len=array.size();
//鲁棒性检查
if(==len) return false;
for(i=;i<len;++i){
if(array[i].size()!=len)
return false;
}
if(array[][]>target)
return false;
if(array[len-][len-]<target)
return false;
for(j=len-;j>=;--j){
//数据不在当前列,跳出循环
if(target<array[][j]||target>array[len-][j])
continue;
for(i=;i<len;++i){
if(target==array[i][j])
return true;
}
}
return false;
}
};
起始这个有更为优化的方式,我是通过列去寻找,有设置while循环,缩减行和列的数值,在逐渐缩小的块状区域寻找
剑指offer习题集1的更多相关文章
- 剑指offer习题集2
1.把数组排成最小的数 class Solution { public: static bool compare(const string& s1, const string& s2) ...
- 剑指offer习题集
1.重载赋值运算符函数:(具体见代码) //普通做法 CMyString& CMyString::operator=(const CMyString& str) { if (this ...
- 剑指Offer面试题:1.实现Singleton模式
说来惭愧,自己在毕业之前就该好好看看<剑指Offer>这本书的,但是各种原因就是没看,也因此错过了很多机会,后悔莫及.但是后悔是没用的,现在趁还有余力,把这本书好好看一遍,并通过C#通通实 ...
- 剑指Offer面试题:14.链表的倒数第k个节点
PS:这是一道出境率极高的题目,记得去年参加校园招聘时我看到了3次,但是每次写的都不完善. 一.题目:链表的倒数第k个节点 题目:输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的习惯,本题 ...
- 《剑指offer》面试题12:打印1到最大的n位数
面试题12:打印1到最大的n位数 剑指offer题目12,题目如下 输入数字n,按顺序打印出1到最大的n位十进制数,比如输入3,则打印出1,2,3一直到最大的三位数999 方法一 和面试题11< ...
- 《剑指offer》面试题11: 数值的整数次方
面试题11: 数值的整数次方 剑指offer面试题11,题目如下 实现函数double power(double base,int exponent),求base的exponent次方, 不得使用库 ...
- 剑指 Offer 题目汇总索引
剑指 Offer 总目录:(共50道大题) 1. 赋值运算符函数(或应说复制拷贝函数问题) 2. 实现 Singleton 模式 (C#) 3.二维数组中的查找 4.替换空格 ...
- 面试题目——《剑指Offer》
1.把一个字符串转换成整数——<剑指Offer>P29 2.求链表中的倒数第k个结点——<剑指Offer>P30 3.实现Singleton模式——<剑指Offer> ...
- 剑指Offer:面试题20——顺时针打印矩阵(java实现)
题目描述: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数 字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1, ...
随机推荐
- iptables基本规则
注意:iptables只能被拥有超级权限的用户设置. 重启 清空 iptables 规则:在终端输入: iptables -F iptables -X iptables -t nat -F i ...
- linux 2.6.21版本的内核合法的MAC地址
当执行ifconfig eth0 hw ether 11:22:33:44:55:66时,当前内核显示修改成功,但是ping时只无限发送ARP包,PC机也已经给板子回ARP包,但没有任何ICMP包的信 ...
- 一步步调试解决iOS内存泄漏
虽然iOS 5.0版本之后加入了ARC机制,由于相互引用关系比较复杂时,内存泄露还是可能存在.所以了解原理很重要. 这里讲述在没有ARC的情况下,如何使用Instruments来查找程序中的内存泄 ...
- 【转】Nginx 安装配置
Nginx("engine x")是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的 Web和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器. ...
- Android Studio实现页面跳转(新页面或者网站)
一,跳转到另一个页面 百度了好久,好像好多种方法,从中挑选了一中比较方便的一中方法 利用Intent类进行实现 1,首先在firstActivity中添加相应的跳转命令代码 例如一下示例代码 if ( ...
- SQL 函数集锦
..STUFF()用另一子串替换字符串指定位置.长度的子串.STUFF (<character_expression1>, <start_ position>, <len ...
- Android 中pid与uid的作用与区别
PID:为Process Identifier, PID就是各进程的身份标识. 程序一运行系统就会自动分配给进程一个独一无二的PID.进程中止后PID被系统回收,可能会被继续分配给新运行的程序,但是在 ...
- linux 远程管理
启动linuxssh 服务: /etc/init.d/ssh 启动网络服务: service network restart linux远程登录配置过程: 首先在ubuntu下安装openssh-se ...
- SPARQL1.1 101 Language and Jena support
1 introduction definition cited from SPARQL 1.1 Overview: SPARQL 1.1 is a set of specifications that ...
- Appium 解决不能输入中文字符问题
只需在初始化driver方法时,写这两行代码即可: capabilities.setCapability("unicodeKeyboard", "True" ...