Oracle首席工程师:技术面试中,怎样的问题才是好问题?( 六 )


但这个过程的前提是 , 一定要给编码留足时间 。 当然 , 如果候选人不能在限定时间内给出清晰的优化后思路 , 那不妨就退一步到原先那个算法角度不那么 “好” , 但是思路清晰的解法上 , 并落实到代码上 。
比方说 , 对于前文所述的那个流量控制的问题 , 候选人在还有半个小时的时候就想到了使用一个时间复杂度为 O(N) 的解 , 而面试官认为时间还比较充裕 , 那就可以尝试挑战一下候选人 “能否再优化一下复杂度” 。
有些时候 , 由于前面的过程磕磕绊绊 , 时间剩下不多了 , 依然只有时间复杂度较高的 brute force 的解法 , 那么将这个解法实现了 , 其实也是一个不错的选择 。
有时候时间实在比较紧张 , 可以要求实现一部分核心代码 , 这些都比由于时间太短而代码写了一半匆匆收尾要好得多 。
我的经验是 , 在讨论充分、思路清晰的情况下 , 代码完成的时间 , 一般只需要 5 到 15 分钟 , 这样的代码量对于面试来说是比较合理的 。
当然 , 相较而言 , 一种更为糟糕的结果是 , 一直到最后 , 讨论的深度依然离编码尚远 , 甚至依然停留在一个很高的泛泛而谈的层面 。
如果在编码完成之后 , 尚有时间 , 优秀的候选人会拿实际的例子去验证代码的正确性 。 而面试官也可以和候选人讨论 “代码后优化” , 比如以下的问题:

  • 你能否进一步优化算法以提高时间/空间复杂度?
  • 如果是工业级别的代码 , 你觉得代码还有哪些问题?
  • 你该怎样去设计测试 , 来保证这段代码的正确性 ?
4、对考察项的覆盖兼有深度和广度
这个问题要能够考察前文所述的技术能力和非技术能力 。
这里说的覆盖 , 不一定要全部覆盖 , 而是要覆盖其中的大部分 , 并且对于每一个考察项要具备一定的考察深度 。
我见到过不少其它的面试风格 , 但我认为这样就一个模糊的主要问题(话题)逐步展开的方式是最好的 。 因为它可以兼具广度和深度的平衡 。
具体来说:
  • 面试很容易走向的一个极端就是考虑广度 , 但缺乏深度 。 比如一种风格是 , 绝大部分的面试时间用来询问候选人的项目和经验 , 让候选人自己介绍 , 而面试官跟进追问 。 这原本是一种很好的方式 , 但是由于候选人对自己的项目通常远比面试官熟悉得多 , 除非明确的同一领域 , 否则面试官较难对于其中的内容挖掘到足够的深度 , 从而识别出候选人是真正做事的人 , 还是夸夸其谈的人 。 这也是这种方式理论可行 , 但实际开展难度较大的原因之一;
  • 另一个极端 , 自然就是考虑深度 , 但缺乏广度 。 比如给出一个过于具体的问题 , 缺乏发挥和迂回的空间 , 对这个问题所涉及的很小一部分深度挖掘 , 甚至纠缠于某个特殊而单一的 case 很长时间 , 但是却只能覆盖很少的考察角度 。
由于深度和广度都是可控的 , 那么这样的可以拿来问不同经验和不同技术背景的工程师候选人 。 这样对于面试官来说 , 可以获得足够的数据 , 便于在遇到新的候选人的时候 , 能够进行横向比较 , 做出更准确的评估 。
比方说 , 过去某级别的候选人能够在面对这个问题的时候 , 能够达到什么样的级别 , 而如今这个候选人有着类似表现 , 这就可以以过去的那个例子来作为参考比较了 。
五、再次回看那个案例
现在 , 让我们再次回到文章开头那个例子问题 , 除了已经提到的考察项的覆盖不够 , 它还有哪些问题呢?
参考上文已经提到了 “好” 问题的标准 , 我觉得其中的这样两条是违背的:
从模糊到清晰:显然 , 问题给出的时候就已经相对比较清晰了 , 这样的方式并不能模拟软件工程师日常面对的许多模糊而困难的实际问题 。 我已经提到 , 对于经验丰富的候选人来说 , 这样的问题无法重现将实际问题映射到软件问题的重要思考过程 。
围绕问题的解决要完整:示例问题的考察过程中 , 只有缺乏互动的编码环节 , 没有其它过程 , 没有编码前的分析、思考和优化 , 也没有编码后的测试、改进和优化 。 考虑到 LRU 完整算法是一个实现代码量偏大的问题 , 拿来放到面试中做一个完整实现 , 由于会消耗过多的时间 , 挤压其它时间 , 因此显得有些过了 。
六、其它 “不好” 的问题
前面说了过于清晰的纯算法题的 “不好” 之处 , 也说了 “好” 问题的例子 , 最后我想再来说几类其它的且典型的 “不好” 的例子 。