剑指offer
date: 7-22
面试流程
面试官谈面试:
- 初级程序员->算法数据结构,看基本功;高级->专业技能、项目经验。
- 对公司近况、项目情况的了解,有合适的问题问面试官。
- 写代码不要急于提交,借助几组用例来测试->高质量代码
技术面
- 基础知识
- 语言、数据结构和算法
- 排序
- 高质量代码(想好特殊的测试用例)
- 特殊输入、边界输入
- NULL指针
- 清晰的思路(递归)
- 优化效率的能力(各种数据结构的优缺点)
- 优秀的综合能力
- (知识迁移、类比的能力)
- 学习能力(对新事物、新概念的理解掌握)
- 抽象建模能力
tip: HR面被拒可能是因为性格不合适、态度不够诚恳。
应聘者提问
- 与自身利益相关
- 不问薪水
- 招聘职位、项目相关
面试基础知识
面试官谈基础知识
* c++基础知识,各种const、引用、面向对象、stl、构造和析构函数
* 设计模式、UML图
* c++内存管理
* 字符串处理(信息论的观点)
* os、语言、算法
语言的基础知识
- sizeof(就是问语言内部细节)
- 空类的实例,大小1(不然无法访问)
- 有构造函数和析构函数(有函数非虚函数):还是1,函数地址在指针定义里,与实例无关
- 有虚函数:实例前会加上虚函数表,32为机器大小4,64位机器大小为8。多重继承则是虚函数表表,大小按类的父类个数及有没有重载父类虚函数相关虚函数表。
- 复制构造函数
- 参数不能传值、只能引用(传值会递归调用本身、造成死循环)
- 重载赋值运算符
- 返回值:本类型的引用(确保能够连续赋值)
- 输入:“const&” 常量引用
- 判断输入、本身是不是一个实例,则不用赋值
- 释放赋值本体的原内存
- 代码复用观点,可以内部调用复制构造函数
- struct和class的不同
- c#中(值类型、引用类型区别,仅限于c#): 权限:都是private;内存:class固定堆上,struct固定栈上
- 访问权限:class默认private,struct默认public
c#
- Finalizer、Dispose析构函数,释放资源。Finalizer由CLR运行时调用。c++则是程序员自己调用
静态构造函数: 类第一次被使用时调用,而且保证只调用一次
细节:第一次调用前:运行静态构造函数;静态构造函数先初始化静态变量,在执行构造代码;若没有静态构造函数,执行默认静态构造函数,初始化静态变量;然后调用构造函数,构造函数先初始化成员变量,然后执行代码。因此次* 顺序为:静态变量->静态构函->成员变量->构造函数
反射、应用程序域(这里先不讨论)
- 多线程环境下的单例模式:要同步加锁。c#中可用静态构造函数实现不用加构造函数锁。
tips:几本书
* 《Effective c++》:面试突击
* 《c++ Primer》:语法,全面了解
* 《Inside c++ object model》:对象内部,sizeof、虚函数等问题
* 《the c++ programming language》: 全面
* 《Professional c#》 :C#与其他语言的区别
* 《CLR Via c#》 :对CLR和.NET做全面剖析。装箱卸箱、垃圾回收、反射。
数据结构
数组与字符串最基础,链表和树出现最多,栈与递归紧密相关,队列与广度优先相关。
- 数组与指针的区别,数组有大小指针无大小,数组作为函数参数时,实际是当做指针的。
指向常量字符串的指针都是相同的,如下所示,1/2相同、3/4不同。
char str3[] = "hello world"; char str4[] = "hello world"; char* str1 = "hello world"; char* str2 = "hello world"; if(str1==str2) printf("str1/2 are the same"); if(str3==str4) printf("str3/4 are the same");
面试题:二维数组中的查找,二分查找
- 面试题:字符串替换空格为%20(求出空间从后往前,原址变换,复杂度O(n))
- vector是动态数组,当空间不够时它会重新申请空间,拷贝数据。
- 链表:
- 面试题5:从尾到头打印链表:将链表指针压倒栈中,然后出栈打印
- 面试题13:在O(1)时间内删除链表节点:删除下一个,将下一个考给自己
- 面试题15: 链表的倒数第k个节点:(1)压栈,空间上浪费时间上2n(2)两个指针p1=p2+k
- 面试题16: 反转链表:(1)压栈(2)遍历反转下一个节点的next指针
- 面试题17:合并两个排序的链表:(1)类似归并排序的合并过程
- 面试题37:两个链表的第一个公共节点:(1)压栈,倒着数第一个不一样的
- 面试题45:“圆圈中最后剩下的数字”(环形链表)
- 面试题27:“二叉树与双向链表”
- 面试题26: “复杂链表的复制”(指向其他节点的链表)?
- 树(复杂指针操作下的树)
- 遍历:前中后序,循环和递归方式。
- 宽度优先遍历:队列实现
- 二叉搜索树、堆、红黑树
- stl中set、multiset、map、multimap使用红黑树实现
- 重建二叉树:分治策略,找根节点再分治
- 栈和队列
- 栈实现队列、队列实现栈
算法和数据操作
- 排序查找(分治策略)
- 手写快排:Partition,QuickSort
- 计数排序:O(n)
- 旋转数组的最小数字,题8
- 递归和循环
- 斐波那契数列(循环好于递归,其实解法是有公式的,题中也有一种公式,《算法导论》计算量那一章,有直接给公式。但是计算量实际没有多大改变)
- 一只青蛙一次可以跳1/2阶台阶,求它跳上n阶有几种跳法->斐波那契数列。
- 从递归关系式可以判断该问题是不是斐波那契问题,f(n)=f(n-1)+f(n-2)。
- 位运算
- 000011010>>2 = 00000010 数字是无符号数,用0填补最左边n位;有符号数,用1填补最左边n位
- 数字中二进制中1的个数:普通解法O(N),循环左移判断是不是1;特殊解法减一与原数相与,则结果是原数的最右边的1变成了0,通过观察能做几次做该操作可以判断有几个1.
date :7-24
高质量的代码
面试官谈代码质量
* 不能只是假象的正常值,要考虑异常输入和资源回收。
* 粗心可以原谅,但是该掌握的知识点没有掌握。(double类型不能用==比较)
* 变量命名规则要规范,要能够选择合适的数据结构