剑指offer
1章面试与简历
先写单元测试用例,再写解决问题的函数,那么我相信面试官肯定会对你刮目相看。
如果应聘者能够熟练地设置断点、单步调试、查看内存、分析调用栈,就能很快发现问题的根源并最终解决问题。

用STAR模型描述简历。
situation 简短的项目背景:项目开发规模,开发的软件的功能目标用户等。
task 自己完成的任务:详细,让别人对自己工作一目了然。注意区分“负责”和“参与”。
action 为完成任务自己做了哪些工作,是怎么做的。这里可以详细介绍。做系统设计的,可以介绍系统架构的特点;做软件开发的,可以写基于什么工具在哪个平台下应用了哪些技术;做软件测试的,可以写是手工测试还是自动化测试、是白盒测试还是黑盒测试等。
Result:自己的贡献。这方面的信息可以写得具体些,最好能用数字加以说明。如果是参与功能开发,则可以说按时完成了多少功能;如果做优化,则可以说性能提高的百分比是多少;如果是维护,则可以说修改了多少个Bug。
关于跳槽的回答:现在的工作做了一段时间,己经没有太多的激情了,因此希望寻找一份更有挑战的工作,然后具体论述
为什么有些厌倦现在的职位,以及面试的职位我为什么会有兴趣。
C++常见问题:
如果写的函数需要传入一个指针,则面试官可能会问是否需要为该指针加上const,把const加在指针不同的位置是否有区别;
如果写的函数需要传入的参数是一个复杂类型的实例,则面试官可能会问传入值参数和传入引用参数有什么区别、什么时候需要为传入的引用参数加上const。
常考察的数据结构:
链表和二叉树相关的问题是很多而试官喜欢问的问题。如果应聘者事先对鲢表的插入和删除节点了如指掌,对二叉树的各种遍历方法的循环和递归与法都烂熟一于胸,那么真正到了面试的时候也就游刃有余了。
常考算法:
大部分公司都会注重考查查找、排序等算法。应聘者可以在了解各种查找和排序算法的基础上,重点掌握二分查找、归并排序和快速排序,因为很多面试题都只是这些算法的变体。
理清思路:
可以试着用一两个具体的例了模拟操作的过程,这样说不定就能通过具体的例子找到抽象的规律。
其次,可以试着用图形表示抽象的数据结构。像分析链表、二叉树相关的题目,我们都可以画出它们的结构来简化题目。
可以试着把复杂的问题分解成若干简单的子问题,再一一解决。很多基于递归的思路,包括分治法和动态规划,都是把复杂的问题分解成一个或者多个简单的子问题。
自己要问的问题:
技术面试不要问薪水。要对应聘的职位或者项目的背景有一定的了解。才好问问题。
2.基础知识
C++概念
1.定义一个空的类型,里面没有任何成员变量和成员函数。对该类型求sizeof,得到的结果是多少?
C++标准要求每个对象必须具有唯一的地址。编译器会为其分配一个最小的大小(通常为1字节)。
2.如果在该类型中添加一个构造函数和析构函数,再对该类型求sizeof,得到的结果又是多少?
结果仍然是1。
普通成员函数(包括构造函数和析构函数)不占用对象的内存空间。成员函数(包括构造函数、析构函数、普通成员函数等)的代码存储在代码段中,而不是每个对象实例中。函数不在类里实现。
对象实例中只需要存储非静态成员变量(如果有的话)和虚函数表指针(如果有虚函数)。如果没有虚函数(即析构函数不是虚的),就不会产生虚函数表指针(vptr)的开销。
3.如果把析构函数标记为虚函数呢?
c++的编译器一旦发现一个类型中有虚函数,就会为该类型生成虚函数表,并在该类型的每一个实例中添加一个指向虚函数表的指针在32位的机器上,一个指针占4字节的空间,因此求sizeof得到4;如果是64位的机器,则一个指针占8字节的空间,因此求sizeof得到8。
很多考查C++语法的代码题重点考查构造函数、析构函数及运算符重载。
面试题3:数组中的重复数字
题目一:找出数组中重复数字
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是2或者3。存在不合法的输入的话输出-1。
官方的思路:直接采用for循环遍历vector数组。在循环里判断i位置的值是不是等于下标。然后判断i位置的值是不是等于以这个值作为下标的那个位置的值,等于了就返回它。就是在交换之前做这么一个判断。交换完后,i--,相当于没有往前遍历,会对交换后的当前位置再次进行检查。最好还是参考书上写的加入边界测试以提高代码的鲁棒性。
题目二:不修改数组找出重复数字
可以开一个n长的数组。但是题目要求不准开n数组。不用O(n)的空间。自己定义了一个二分的区间,时间复杂度为logn。每次去数组里数数字个数看在不在当前的二分区间里,以此来判断该切换到哪个二分区间去。二分的midle还可以这样写:
midle = ((end- start) >> 1) + start。
为了探查边界,循环条件可以写while(end >= start)。
二分到了最后一步,start和midle为同一个时,也要能被数到。
面试题4:二维数组中的查找
由于这个数组从左到右,从上到下是递增的。我们每次从右上角开始选取数字和要找的target作比较。大于target则搜索的列数colums减减,小于target则搜索的行数加加。
如果恰好从右上角来分析问题的话,这个题目就很有可能迎刃而解。
面试题5:替换空格
链表
-> 运算符时,它表示通过指针访问所指向对象的成员(成员变量或成员函数)。指针->成员 完全等价于 (*指针).成员。struct ListNode { int m_nValue; ListNode* m_pNext; };
往该链表末尾添加一个节点:
1.先new一个结点对象,给他赋值。
2.创建临时结点指针,保存头结点防止头结点地址丢失。
3.遍历链表,在pNext为空时停止。void AddToTail(ListNode** pHead, int value) { ListNode* pNew = new ListNode(); //先new一个结点对象,给他赋值 pNew->m_nValue = value; pNew->m_pNext = nullptr; if (*pHead == nullptr) { *pHead = pNew; return; } else { ListNode* pNode = *pHead; //创建临时结点指针,保存头结点防止头结点丢失 while (pNode->m_pNext != nullptr) { pNode = pNode->m_pNext; //遍历链表,在pNext为空时停止 } pNode->m_pNext = pNew; } }

浙公网安备 33010602011771号