2020年2月28日 下午12:20
- 期望所有调用它的客户模块都保证一定的进入条件:这就是函数的 先验条件 —客户的义务和供应商的权利,这样它就不用去处理不满足先验条件的情况。
- 保证退出时给出特定的属性:这就是函数的 后验条件 —供应商的义务,显然也是客户的权利。
- 在进入时假定,并在退出时保持一些特定的属性: 不变条件 。
白板编程浅谈——Why, What, How | lucida
认为程序员可以被分为两种:
- 先确认前条件_不变式_终止条件/边界条件,然后写出正确的代码
- 先编写代码,然后通过各种用例_测试_调试对程序进行调整,最后得到似乎正确的代码
白板编程的目标并不是要求面试者一下子写出完美无缺的代码,而是:
- 让面试者在解题的过程中将他/他的思维过程和编码习惯展现在面试官面前,以便面试官判定面试者是否具备清晰的逻辑思维和良好的编程素养
- 如果面试者陷入困境或是陷阱,面试官也可以为其提供适当的辅助,以免面试陷入无人发言的尴尬境地
1.确定需求
- 面试者在白板编程时最重要的任务是理解题目,确认需求——确定输入_输出,确定数据范围,确定时间_空间要求,确定其它限制。以最常见的排序为例:
- 输入:来自数组?链表?或是不同的机器?
- 输出:是否有重复?是否要求稳定?
- 数据范围:排序多少个元素?100 个? 100 万个? 1 亿个?这些元素是否在某个范围内?
- 时间要求:1 分钟?1 刻钟?一小时?
- 空间要求:是否常量空间?是否可以分配新的空间?如果可以,能分配多少空间?是否在内存中排序?
- 其它限制:是否需要尽可能少的赋值?是否需要尽可能少的比较?
- 有时面试官不会把题目说的特别清楚,这时就需要面试者自己去确认这些需求,不要认为这是在浪费时间,不同的需求会导致截然不同的解法,此外确认需求会留给面试官良好的印象。
2.白板编程
理解题目确认需求之后,面试者就可以开始在白板上编写代码,下面是一些我自己的白板编程经验:
- ::先写出轮廓(大纲)::
- 白板编程没法复制粘贴,所以后期调整代码结构非常困难。因此我们最好在开头写出程序的大致结构,从而保证之后不会有大改;
- ::确定前条件_不变式_后条件::
- 我们可以通过注释的形式给出代码的前条件_不变式_后条件
- 使用实例数据验证自己的程序
- 尽管不变式足以验证程序的正确性,但适当的使用实例数据会大大增强代码的可信性
- 使用缩写
- 白板编程并不需要面试者在白板上写出能够一次通过编译的代码。为了节省时间,面试者可以在和面试官沟通的基础上使用缩写。例如使用 Iter 替代 Iterable,使用 BQ 替代 BlockingQueue。(此法尤其适合于 Java -_-#)
- 至少留一行半行宽
- 出于紧张或疏忽,一般面试者在白板编程时会犯下各种小错误,例如忘了某个判断条件或是漏了某条语句,空余的行宽可以帮助面试者快速修改代码,使得白板上的代码不至于一团糟。
3.不会做怎么办
相信大多数面试者都碰到过面试题不会做的情况,这里说说我自己的对策:
- 至少先给出一个暴力(Brute force)解法
- 寻找合适的数据结构(例如栈_队列树堆_图)和算法(例如分治_回溯_动态规划/贪婪)
- 从小数据集开始尝试
- 如果还是没有头绪,重新考虑题目的前条件,思考是否漏掉了条件(或是隐含的条件)
- 如果 3 分钟过后还是没有任何思路,请求面试官提示,不要觉得不好意思——经过提示给出答案远强于没有答案
- 我是一个功利主义者( Utilitarianism )