Happy剑指offer:第2章题目笔记
概念题
定义一个空的类,里面没有任何成员变量和成员函数。对该类型求sizeof,会得到的结果是1。因为虽然没有成员变量和成员函数,没有有用信息,但是声明实例的时候,它必须在内存之中占用一定的空间,空间的大小由编译器决定,Visual Studio其分配空间为1。哪怕类内定义了构造函数和析构函数,这个结果仍然不会改变,仍然会是1。因为在实例需要初始化或者析构的时候,只需要调用这两个函数,即取得这两个函数的地址即可。这两个函数不会为实例增添任何内容。
在上面的例子之中,如果把析构函数构造成虚函数,那么结果会发生变化。这是因为编译器一旦发现类之中有虚函数,那么它一定会生成一个指向虚函数的虚函数表。在虚函数表之中,生成一个指向虚函数表的指针,指针的大小随系统的位数决定。32位系统指针占用4个字节,求sizeof之后,结果为4,64为系统占用8个字节,最终结果为8 。
判断题1
涉及到的一个问题是类内赋值构造函数的传值问题。如果允许复制构造函数传值,就会在赋值构造函数内部递归一般的进行对复制构造函数的调用,最终必然导致栈溢出。
如果仔细观察就会发现,如果要是调用 复制构造函数,赋值构造函数的输入参数必然是引用形式。
举例;
A(const A &other)
面试题1
自己在定义一个类的时候,对构造函数,仍然会有一点点的不确定。
尝试了一把运算符重载。感觉还好,注意的是
1. 输入为引用,输出为引用
2. 对于指针,注意分配内存和释放内存。
内存泄露指的是在定义指针之后为其动态分配了内存,但是在使用完毕之后并未释放该内存。导致该内存一直被占用。其实说白了就是该内存空间使用完毕之后未回收。
//offer1 class CMyString { public:CMyString(char* pData = NULL);//这个应该只能算是声明吧CMyString(const CMyString& str);~CMyString(void);CMyString& operator =(const CMyString &str); private:char* m_pData; }; CMyString& CMyString::operator = (const CMyString &str) {if (this == &str)return *this;delete[]m_pData;m_pData == NULL;m_pData = new char[strlen(str.m_pData) + 1];strcpy(m_pData, str.m_pData);return *this; }
面试题2
singleton模式:即单例模式。数学与逻辑学中,singleton定义为“有且仅有一个元素的集合”
如果一个类和singleton模式相关联,那么毫无疑问,这是一个特殊类,因为这种类只有一个对象,所以称为单例,单个例子嘛。一般这种单例非常容易被外界访问。
优点:节约系统资源。
生成实例的方法是静态方法。
//offer2 实现singleton模式 class Singleton { public:static Singleton& GetInstance(){static Singleton Instance;return Instance;} private:Singleton();Singleton(const Singleton& other);~Singleton();Singleton& operator=(const Singleton& other); };
面试题3
注意int* matrix只能是代表一维数组。思路知道之后这道题突然间变得好简单。
//offer3 bool Find(int* matrix, int rows, int columns, int number) {bool IsFound = false;if (matrix != NULL && rows > 0 && columns > 0){int row = rows-1;int column = 0;while (row >= 0 && column < columns){if (matrix[row*columns + column] == number){IsFound = true;break;}else{if (matrix[row*columns + column] < number){++column;}else{--row;}}}}return IsFound; }
判断题2:
两个字符串均定义为char str[]类型的时候,判断两个字符串是否相等,需要判定两个是不是指向相同的内存空间。这个问题十分重要。并非内容一样就可以的。另一种:char* str就不存在这个问题。它们定义的时候会自动指向对应的内存地址的。
面试题4:
//offer4 void ReplaceBlank(char str[], int length) {if (str == NULL || length < 0)return;int LengthOriginal = strlen(str);int LengthNew = LengthOriginal;int i = 0;while (str[i] != '\0'){if (str[i] == ' '){LengthNew += 2;}++i;}int IndexOri = LengthOriginal;int IndexNew = LengthNew;while (IndexOri >= 0 && IndexNew > IndexOri)//IndexNew>IndexOri如果前面一大片都没有空格的话,那么这个判断可以节约很多时间 {if (str[IndexOri] == ' '){str[IndexNew--] = '0';str[IndexNew--] = '2';str[IndexNew--] = '%';}elsestr[IndexNew--] = str[IndexOri];IndexOri--;} }
面试题4附加题
void InerstNumber(int* arr1, int length1,int* arr2, int length2,int length) {if (arr1 == NULL || length < 0)return;if (arr2 == NULL){arr2 = arr1;return;}if (length1 + length2>length)return;int index1 = length1-1;int index2 = length2-1;int index3 = length1 + length2-1;while (index1>=0&&index2>=0&&index3 >=0 ){if (arr1[index1] > arr2[index2]){arr2[index3--] = arr1[index1--];}else if (arr1[index1] < arr2[index2]){arr2[index3--] = arr2[index2--];}else{arr2[index3--] = arr2[index2--];arr2[index3--] = arr1[index1--];}}if (index2 < 0){while (index1>=0)arr2[index3--] = arr1[index1--];} }
在链表的尾部添加结点
void AddToTail(ListNode **pHead, int value) {ListNode* pNew = new ListNode();pNew->m_nValue = value;pNew->m_pNext = NULL;if (*pHead == NULL){*pHead = pNew;}else{ListNode* pNode = *pHead;while (pNode->m_pNext != NULL)pNode = pNode->m_pNext;pNode->m_pNext = pNew;} }
删除一个节点
void RemoveNode(ListNode** pHead, int value) {if (pHead == NULL || *pHead == NULL)return;ListNode* pToBeDeleted;if ((*pHead)->m_nValue == value){pToBeDeleted = *pHead;*pHead = (*pHead)->m_pNext;}else{ListNode* pNode = *pHead;while (pNode->m_pNext != NULL&&pNode->m_pNext->m_nValue != value)pNode = pNode->m_pNext;if (pNode->m_pNext != NULL&&pNode->m_pNext->m_nValue == value){pToBeDeleted = pNode->m_pNext;pNode->m_pNext = pNode->m_pNext->m_pNext;}}if (pToBeDeleted != NULL){delete pToBeDeleted;pToBeDeleted = NULL;} }
面试题5从尾到头打印链表。这道题可以在栈的帮助下用迭代的方式实现。或者使用递归方式实现。
迭代方式:
void PrintListNode(ListNode* pHead) {if (pHead == NULL)return;ListNode* pNode = pHead;stack<ListNode*> nodes;while (pNode != NULL){nodes.push(pNode);pNode = pNode->m_pNext;}while (!nodes.empty()){pNode = nodes.top();nodes.pop();cout << pNode->m_nValue << "\t";} }
递归方式
//从尾到头打印链表,递归方式 void PrintListNode_Recursively(ListNode* pHead) {ListNode* pNode = pHead;if (pNode != NULL){if (pNode->m_pNext != NULL){PrintListNode_Recursively(pNode->m_pNext);}}cout << pNode->m_nValue << "\t"; }
//面试题6 重建二叉树 BinaryTreeNode* Construct(int* PreOrder, int* Inorder, int length) {if (PreOrder == NULL || Inorder == NULL || length <= 0)return NULL;elsereturn ConstructCore(PreOrder, PreOrder + length - 1, Inorder, Inorder + length - 1); }BinaryTreeNode* ConstructCore(int* PreOrderStart, int* PreOrderEnd, int* InOrderStart, int*InOrderEnd) {int RootValue = PreOrderStart[0];BinaryTreeNode* Root = new BinaryTreeNode();Root->m_nValue = RootValue;Root->m_pLeft = Root->m_pRight = NULL;if (PreOrderEnd == PreOrderStart){if (InOrderStart == InOrderEnd&&InOrderStart[0] == RootValue)return Root;if (InOrderStart == InOrderEnd&&InOrderStart[0] != RootValue)throw exception("Invalid Input");}//构建左右子树int* PreLeftRoot = PreOrderStart + 1;int LeftTreeLength = 0;int* InRoot = InOrderStart;while (InRoot!=InOrderEnd&&*InRoot != RootValue){InRoot++;LeftTreeLength++;}if (InRoot == InOrderEnd&&*InRoot != RootValue)throw exception("Invalid Input");if (LeftTreeLength > 0){Root->m_pLeft = ConstructCore(PreOrderStart + 1, PreOrderStart + LeftTreeLength, InOrderStart, InOrderStart + LeftTreeLength - 1);}if (LeftTreeLength < InOrderEnd - InOrderStart){Root->m_pRight = ConstructCore(PreOrderStart + LeftTreeLength + 1, PreOrderEnd, InRoot + 1, InOrderEnd);} }
//用两个堆栈做成一个队列 template<typename T>class CQueue { public:CQueue();~CQueue(void);void AppendTail(const T& node);T& DeleteHead(); private:stack<T> stack1;stack<T> stack2; };template<typename T> void CQueue::AppendTail(const T& node) {stack1.push(node); }template<typename T> T& CQueue::DeleteHead() {if (stack2.empty()){if (!stack1.empty()){while (!stack1.empty()){T& node = stack1.top();stack1.pop();stack2.push(node);}}elsethrow exception("Invalid Input");}T node2 = stack2.top();stack2.pop();return node2; }
用两个队列实现一个堆栈的方法和上面类似。只要充分利用队列先进先出和堆栈后进先出的特点即可。
template<typename T>T CStack::DeleteHead(const T& node) {if (q1.empty()){while (!q2.empty()){T& node = q2.top();q2.pop();if (!q2.empty())q1.push(node);}}else{while (!q1.empty()){T& node = q1.top();q1.pop();if (!q1.empty())q2.push(node);}} }
//快速排序 void swap(int &a, int &b) {int temp;temp = a;a = b;b = temp; } int Partition(int data[], int length, int start, int end) {if (data == NULL || length <= 0 || start < 0 || end >= length)throw exception("Invalid Input");int index = (start + end) / 2;int small = start - 1;swap(data[index], data[end]);for (int index = start; index < end; ++index){if (data[index] < data[end]){++small;if (small != index)swap(data[small], data[index]);}}++small;swap(data[small], data[end]);return small; }void QuickSort(int data[], int length, int start, int end) {if (start == end)return;int index = Partition(data, length, start, end);if (index>start)QuickSort(data, length, start, index - 1);if (index < end)QuickSort(data, length, index + 1, end); }
转载于:https://www.cnblogs.com/chengxuyuanxiaowang/p/4242619.html
Happy剑指offer:第2章题目笔记相关推荐
- 《剑指offer》第二章小结(1)——链表的基本操作
<剑指offer>第二章小结(1)--链表的基本操作 面试题5是从尾到头打印链表,与此相关的链表的基本操作应该知道. 下面代码中列举了单链表的创建.遍历.插入和删除四种操作.参考网址: h ...
- 《剑指 Offer I》刷题笔记 51 ~ 61 题
<剑指 Offer I>刷题笔记 51_60 位运算(简单) 51. 二进制中 1 的个数 _解法1:逐伟判断 解法2:巧用 n&(n-1) 52. 不用加减乘除做加法(背题) 解 ...
- 《剑指 Offer I》刷题笔记 41 ~ 50 题
<剑指 Offer I>刷题笔记 41_50 排序(中等) 41. 最小的k个数# _解法1:排序 API + 数组复制 API 42. 数据流中的中位数 _解法1:暴力 搜索和回溯算法( ...
- 《剑指 Offer I》刷题笔记 20 ~ 30 题
<剑指 Offer I>刷题笔记 20_30 动态规划(简单) 20. 斐波那契数列 _解法1:迭代 解法2:记忆化递归 解法3:动态规划 21. 青蛙跳台阶问题 _解法1:动态规划 22 ...
- 《剑指 Offer I》刷题笔记 11 ~ 19 题
<剑指 Offer I>刷题笔记 11 ~ 19 题 查找算法(中等) 11. 二维数组中的查找 _解法 1:暴力迭代 解法 2:标志数 解法 3:逐行二分 12. 旋转数组的最小数字 _ ...
- 《剑指 Offer I》刷题笔记 1 ~10 题
<剑指 Offer I>刷题笔记 1 ~10 题 栈与队列(简单) 1. 用两个栈实现队列 _解法 1:暴力做法 解法 2:优化解法 1 2. 包含 min 函数的栈 _解法 1:pop( ...
- Java算法:牛客网Java版剑指Offer全套算法面试题目整理及电子档,Java算法与数据结构面试题,面试刷题、背题必备!牛客网剑指offer
剑指offer(java版) 牛客网Java版剑指Offer全套题目67道 资源来源于网络 目录 1.二维数组中的查找 2.替换空格 3.从尾到头打印链表 4.重建二叉树 5.用两个栈实现队列 6.旋 ...
- 剑指Offer(1)——第一章面试的流程
目录 前言 正文 一.经验 二. 常见题目 1. 把一个字符串转换成整数 2. 求链表中的倒数第n个节点 三.测试相关内容 1. 白盒测试 2. 黑盒测试 3. 自动化测试 参考 前言 剑指Offer ...
- 【剑指Offer】面试招聘题目2:重建二叉树
题目链接:http://ac.jobdu.com/problem.php?cid=1039&pid=1 题目描述: 题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输 ...
- 《剑指offer》第二章——关于面试官王海波的思考
一.C++基础知识 1.面向对象的特性:封装.继承和多态. 所谓封装,就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏.简单的说,一个类就是一 ...
最新文章
- 如何去除矩阵中的NaN元素
- 从实例入手学习使用vue+axios配置代理进行跨域访问百度音乐API
- Velocity浅析及与Jsp、Freemarker对比
- 必填校验加变色,点击颜色消失
- Frame帧动画帧布局Android
- Go Revel - Cache(缓存)
- Ztree 改 节点
- php str_replace技巧-避免重复替换
- eclipse经常出现弹窗Refreshing workspace
- 管理感悟:开会为什么坐到后面
- en55032最新标准下载_欧盟新EMC标准EN55032
- 警惕:ERP系统不堪重负的几大预警信号
- oppoa5降级教程_OPPO A5官方出厂rom系统刷机包下载_卡刷升级包降级回退包
- 安装Microsoft Visual Studio 2010 Service Pack 1 ,系统无法找到指定的对象
- 什么是jsp,什么是Servlet?jsp和Servlet有什么区别?
- 小丁带你走进git世界五-远程仓库
- NOR FLASH (mx25u12835f) lock/unlock功能及linux对其支持
- 直播平台源码开发过程中关于Git上传的简单操作说明
- 工作记录|在PyTorch下读取GloVe向量
- 什么是医嘱?医嘱的书写内容?