编辑推荐
                                        《程序员面试金典》作者Gayle Laakmann McDowell是著名的软件从业者,曾担任谷歌资深面试官和招聘委员会成员,深谙世界科技公司的面试之道,与数百名求职者有过“交锋”,洞悉面试成败的关键所在。
  《程序员面试金典》融萃了作者在世界科技公司长期从事相关工作所积累的面试经验,涉及与面试相关的每个环节——大到剖析面试流程、详解经典的技术面试题,小到如何制作简历及面试时的着装规范,你都能在书中找到锦囊妙计。
  对源自微软、苹果、谷歌等IT名企的150道面试题进行深入解析,是本书的重头戏,这些面试题数量众多、质量上乘、解析深入,是目前市面上同类图书均无法比肩的。对于希望冲击IT名企、期望大展宏图的程序员来说,《程序员面试金典》是不可或缺的含金量极高的面试秘籍。
      内容简介
     《程序员面试金典》是原谷歌面试官的经验之作,层层紧扣程序员面试的每一个环节,全面而详尽地介绍了程序员应当如何应对面试,才能在面试中脱颖而出。第1~7 章主要涉及面试流程解析、面试官的幕后决策及可能提出的问题、面试前的准备工作、对面试结果的处理等内容;第8~9 章从数据结构、概念与算法、知识类问题和附加面试题4 个方面,为读者呈现了出自微软、苹果、谷歌等多家知名公司的150 道编程面试题,并针对每一道面试题目,分别给出了详细的解决方案。
  《程序员面试金典》适合程序开发和设计人员阅读。     
作者简介
     Gayle Laakmann McDwell,美国求职咨询网站CareerCup.cm创始人兼CE,是一位软件工程师,曾在微软、苹果与谷歌任职。早先,她自己就是一位十分成功的求职者,成功通过了微软、谷歌、、苹果、IBM、高盛等多家企业极其严苛的面试过程。工作以后,她又成为一位出色的面试官。在谷歌任职期间,她还是该公司面试官及招聘委员会成员,期间阅人无数,积累了相当丰富的面试经验。除此书外,还著有《金领简历:敲开苹果、微软、谷歌的大门》。
  译者简介:
  李琳骁,从事嵌入式Linux内核/驱动开发,关注IT、开放源码和安防监控等领域。业余时以技术翻译为乐,时而客串编辑,好为爱书挑错,渴求完美,却也常因“小”失大,不得读书要领。翻译或参与翻译了《Linux命令详解手册》《编程人生》《编程大师访谈录》等图书。
  漆犇,毕业于地质大学,拥有十余年软件开发、测试及流程管理经验,曾翻译出版了《Linux/Unix设计思想》《金领简历 : 敲开苹果、微软、谷歌的大门》等书。目前定居于美国西雅图,在微软Windws Phne开发中心从事与WP应用开发者相关的项目管理事务。     
内页插图
          精彩书评
     ★“如果你正打算参加技术面试,我极力推荐你阅读此书。这本书汇总了诸多你不可不知的决胜于技术面试的问题、策略和方法。”
  ——Ginnie,读者     
目录
   第1章 面试流程
1.1  概述
1.2  面试题的来源
1.3  准备时间表与注意事项
1.4  面试评估流程
1.5  答题情况
1.6  着装规范
1.7  十大常见错误
1.8  常见问题解答
第2章 面试揭秘
2.1  微软面试
2.2  亚马逊面试
2.3  谷歌面试
2.4  苹果面试
2.5  Facebook面试
2.6  雅虎面试
第3章 特殊情况
3.1  有工作经验的求职者
3.2  测试人员及SDET
3.3  项目经理与产品经理
3.4  技术主管与部门经理
3.5  创业公司的面试
第4章 面试之前
4.1  积累相关经验
4.2  构建人际网络
4.3  写好简历
第5章 行为面试题
5.1  准备工作
5.2  如何应对
第6章 技术面试题
6.1  技术准备
6.2  如何应对
6.3  算法题的五种解法
6.4  怎样才算好代码
第7章 录用通知及其他
7.1  如何处理录用与被拒的情况
7.2  如何评估录用待遇
7.3  录用谈判
7.4  入职须知
第8章 面试考题
8.1  数组与字符串
8.2  链表
8.3  栈与队列
8.4  树与图
8.5  位操作
8.6  智力题
8.7  数学与概率
8.8  面向对象设计
8.9  递归和动态规划
8.10  扩展性与存储限制
8.11  排序与查找
8.12  测试
8.13  C和C++
8.14  Java
8.15  数据库
8.16  线程与锁
8.17  中等难题
8.18  高难度题
第9章 解题技巧
9.1  数组与字符串
9.2  链表
9.3  栈与队列
9.4  树与图
9.5  位操作
9.6  智力题
9.7  数学与概率
9.8  面向对象设计
9.9  递归和动态规划
9.10  扩展性与存储限制
9.11  排序与查找
9.12  测试
9.13  C和C++
9.14  Java
9.15  数据库
9.16  线程与锁
9.17  中等难题
9.18  高难度题
索引      
前言/序言
     招聘中的问题
  讨论完招聘事宜,我们又一次沮丧地走出会议室。那天,我们重新审查了十位“过关”的求职者,但是全都不堪录用。我们很纳闷,是我们太过苛刻了吗?
  我尤为失望的是,我推荐的一名求职者也被拒了。他是我以前的学生,以高达3.73的平均分(GPA)毕业于华盛顿大学,这可是世界上最棒的计算机专业院校之一。此外,他还完成了大量的开源项目工作。他精力充沛、富于创新、踏实能干、头脑敏锐,不论从哪方面来看,他都堪称真正的极客。
  但是,我不得不同意其他招聘人员的看法:他还是不够格。就算我的强力推荐可以让他侥幸过关,在后续的招聘环节还是会失利,因为他的硬伤太多了。
  尽管面试官都认为他很聪明,但他答题总是磕磕绊绊的。大多数成功的求职者都能轻松搞定第一道题(这一题广为人知,我们只是略作调整而已),可他却没能想出合适的算法。虽然他后来给出了一种解法,但没有提出针对其他情形进行优化的解法。最后,开始写代码时,他草草地采用了最初的思路,可这个解法漏洞百出,最终还是没能搞定。他算不上表现最差的求职者,但与我们的“录用底线”却相去甚远,结果只能是铩羽而归。
  几个星期后,他给我打电话询问反馈意见,我很纠结,不知该怎么跟他说。他需要变得更聪明些吗?不,他其实智力超群。做个更好的程序员?不,他的编程技能和我见过的一些最出色的程序员不相上下。
  跟许多积极上进的求职者一样,他准备得非常充分。他研读过Brian W. Kernighan和Dennis M. Ritchie合著的《C程序设计语言》,麻省理工学院出版的《算法导论》等经典著作。他可以细数很多平衡树的方法,也能用C语言写出各种花哨的程序。
  我不得不遗憾地告诉他:光是看这些书还远远不够。这些经典学院派著作教会了人们错综复杂的研究理论,对程序员的面试却助益不多。为什么呢?容我稍稍提醒你一下:即使从学生时代起,你的面试官们其实都没怎么接触过所谓的红黑树(Red-Black Trees)算法。
  要顺利通过面试,就得“真枪实弹”地做准备。你必须演练真正的面试题,并掌握它们的解题模式。
  这本书就是我根据自己在顶尖公司积累的第一手面试经验提炼而成的精华。我曾经与数百名求职者有过“交锋”,本书可以说是我面试几百位求职者的结晶。同时,我还从成千上万求职者与面试官提供的问题中精挑细选了一部分。这些面试题出自许多知名的高科技公司。可以说,这本书囊括了150道世界上最好的程序员面试题,都是从数以千计的好问题中挑选出来的。
  我的写作方法
  本书重点关注算法、编码和设计问题。为什么呢?尽管面试中也会有“行为问题”,但是答案会随个人的经历而千变万化。同样,尽管许多公司也会考问细节(例如,“什么是虚函数?”),但通过演练这些问题而取得的经验非常有限,更多地是涉及非常具体的知识点。本书只会述及其中一些问题,以便你了解它们“长”什么样。当然,对于那些可以拓展技术技能的问题,我会给出更详细的解释。
  我的教学热情
  我特别热爱教学。我喜欢帮助人们理解新概念,并提供一些学习工具,从而充分激发他们的学习热情。
  我第一次“正式”的教学经验是在美国宾夕法尼亚大学就读期间,那时我才大二,担任本科计算机科学课程的助教(TA)。我后来还在其他一些课程中担任过助教,最终在大学里推出了自己的计算机科学课程,也就是给大家教授一些实际的“动手”技能。
  在谷歌担任工程师时,培训和指导“Nooglers”(意指谷歌新员工。没错,他们就是这么称呼新人的!)是我最喜欢的工作之一。后来,我还利用“20%自由支配时间”在华盛顿大学教授计算机科学课程。
  《程序员面试金典》、《金领简历》和CareerCup.com网站都能充分体现我的教学热情。即便是现在,你也会发现我经常出现在CareerCup.com上为用户答疑解惑。
  请加入我们的行列吧!
  Gayle Laakmann McDowell    
				
 
				
				
					《深入探索:算法与数据结构精讲与实战》  第一章:基础篇——构建坚实的知识地基  本章将带您系统性地回顾并深入理解算法与数据结构的基础概念,为后续的实战章节打下坚实的地基。我们将从最核心的元素出发,摒弃浮光掠影的介绍,深入探究其本质和应用场景。     数据结构:组织的艺术        数组(Arrays): 不仅是简单的线性序列,我们将剖析其内存布局、访问效率,以及在不同编程语言中的具体实现差异。我们会探讨一维、多维数组的特性,以及它们在实际问题中的灵活运用,例如矩阵运算、图像处理的初步概念。        链表(Linked Lists): 从单向链表到双向链表,再到循环链表,我们将详细讲解节点结构、指针操作以及各种操作(插入、删除、查找)的时间复杂度。重点会放在链表在动态内存管理、实现其他数据结构(如栈、队列)时的优势,以及避免常见的指针失效问题。        栈(Stacks)与队列(Queues): 这两个“后进先出”(LIFO)与“先进先出”(FIFO)的抽象数据类型,我们将深入理解其在函数调用、表达式求值、广度优先搜索(BFS)等场景下的核心作用。会详细讲解基于数组和链表的实现方式,并比较它们的性能优劣。        哈希表(Hash Tables)/散列表: 理解哈希函数的设计原则(均匀性、快速计算),冲突解决方法(链地址法、开放地址法),以及其在高效查找、去重、计数等方面的强大能力。我们将分析不同哈希函数和冲突解决策略对性能的影响。        树(Trees):            二叉树(Binary Trees): 重点介绍二叉搜索树(BST)的查找、插入、删除操作,并深入探讨其平衡性问题,引入 AVL 树和红黑树的概念,分析它们的自平衡机制和时间复杂度保证。            堆(Heaps): 分别讲解最大堆和最小堆,理解其在优先队列、堆排序中的应用,以及它们如何通过数组高效表示。        图(Graphs): 介绍图的定义(顶点、边),表示方法(邻接矩阵、邻接表),并为后续章节的图遍历算法奠定基础。     算法:解决问题的智慧        算法复杂度分析(Big O Notation): 这是理解算法效率的关键。我们将详细讲解时间复杂度和空间复杂度,并通过大量实例演示如何分析一个算法的复杂度,包括常数时间 O(1)、对数时间 O(log n)、线性时间 O(n)、线性对数时间 O(n log n)、平方时间 O(n^2) 等,以及最坏情况、平均情况和最好情况分析。        递归(Recursion): 深入理解递归的定义、基线条件(base case)和递归步骤(recursive step)。我们会通过经典问题(如阶乘、斐波那契数列、汉诺塔)来演示递归的思维方式,并讲解递归的效率问题(栈溢出、重复计算)以及如何通过记忆化(memoization)或动态规划(dynamic programming)来优化。        排序算法(Sorting Algorithms):            简单排序: 冒泡排序、插入排序、选择排序,理解它们的基本原理和 O(n^2) 的时间复杂度,以及在特定场景下的适用性。            高效排序: 归并排序(Merge Sort)、快速排序(Quick Sort)、堆排序(Heap Sort),深入分析它们的 Divide and Conquer(分治)策略,以及 O(n log n) 的时间复杂度。我们将详细讲解快速排序的枢密选择(pivot selection)和分区(partitioning)过程,并分析其在实践中的性能表现。            特殊排序: 计数排序(Counting Sort)、桶排序(Bucket Sort)、基数排序(Radix Sort),理解它们的适用范围和线性时间复杂度 O(n+k) 或 O(nk) 的原理。        查找算法(Searching Algorithms):            线性查找(Linear Search): 简单直接,但效率较低。            二分查找(Binary Search): 在有序数组中的高效查找,时间复杂度为 O(log n),我们将详细讲解其工作原理和边界条件处理。  第二章:进阶篇——算法的精妙设计与优化  在掌握了基础数据结构和算法后,本章将聚焦于更复杂、更具挑战性的算法设计范式和优化技巧,帮助您构建解决实际问题的强大武器库。     分治法(Divide and Conquer): 深入理解其“分解-解决-合并”的思想。除了在排序算法中的应用,我们还会探讨其在计算几何、数值计算等领域的应用,例如计算最近点对问题。    动态规划(Dynamic Programming): 这是解决重叠子问题和最优子结构问题的强大技术。我们将从理解“状态转移方程”出发,通过一系列经典问题(如背包问题、最长公共子序列 LCS、最长递增子序列 LIS、矩阵链乘法)来演示如何构建 DP 模型、定义状态、编写递推关系,并优化空间复杂度。    贪心算法(Greedy Algorithms): 理解贪心策略的核心——在每一步选择局部最优解,期望得到全局最优解。我们将分析贪心算法适用的条件(贪心选择性质和最优子结构性质),并通过活动选择问题、霍夫曼编码、最小生成树(Prim/Kruskal)等例子来展示其应用。    回溯法(Backtracking): 学习如何系统地搜索解空间,通过“试探”和“撤销”来寻找所有可能的解。我们将通过 N 皇后问题、组合总和、全排列等经典问题来阐述回溯法的框架和剪枝技巧,以提高搜索效率。    图算法:探索连接的奥秘        图的遍历:            深度优先搜索(DFS): 讲解其递归或栈实现方式,以及在判断连通性、拓扑排序、寻找回路等方面的应用。            广度优先搜索(BFS): 讲解其队列实现方式,以及在寻找最短路径(无权图)、层级遍历等方面的应用。        最短路径算法:            Dijkstra 算法: 学习如何在带权图(非负权)中找到单源最短路径,理解其优先队列的应用和时间复杂度。            Bellman-Ford 算法: 掌握如何在带权图(可含负权)中找到单源最短路径,并能检测负权回路。            Floyd-Warshall 算法: 理解如何在带权图(可含负权)中找到所有顶点对之间的最短路径。        最小生成树(Minimum Spanning Tree - MST):            Prim 算法: 学习如何从一个顶点开始,逐步构建最小生成树。            Kruskal 算法: 学习如何按边的权重排序,并使用并查集(Disjoint Set Union - DSU)来构建最小生成树。        拓扑排序(Topological Sort): 学习如何在有向无环图(DAG)中找到顶点的线性序列,使其满足从某个顶点到另一个顶点的所有路径都必须经过前者。  第三章:实战篇——解决真实世界的挑战  本章将把前两章学到的理论知识付诸实践,通过一系列精心挑选的、涵盖了常见技术面试场景的实际问题,帮助您巩固所学,提升解决问题的能力。我们将不仅仅是给出代码,更会侧重于分析问题的本质,选择合适的数据结构和算法,并进行性能优化。     字符串处理的高级技巧:        KMP 算法(Knuth-Morris-Pratt):高效的字符串匹配算法,深入理解其前缀函数(next 数组)的构建和应用。        Manacher 算法:解决回文子串问题的线性时间算法。        字符串的编码与解码,例如 Base64。    面试中的常见数据结构应用:        LRU 缓存(Least Recently Used Cache): 结合哈希表和双向链表实现,考察对数据结构组合的理解。        滑动窗口(Sliding Window): 在数组或字符串中寻找满足特定条件的子段,考察对数组和指针的灵活运用。        前 K 个元素问题: 利用堆(优先队列)或快速选择算法来高效解决。        两数之和、三数之和等: 考察对哈希表、排序、双指针等技巧的综合运用。    并发与线程安全(初步): 简要介绍线程、进程的概念,以及在多线程环境下数据共享可能遇到的问题(竞态条件、死锁),为后续更深入的学习打下基础。    位运算的巧妙应用: 学习如何利用位运算实现高效的计数、开关、状态标记等操作,例如判断奇偶性、交换变量、判断是否为 2 的幂次方等。    数学与概率在算法中的应用: 介绍一些常见的数学公式和概率模型,以及它们如何辅助算法设计,例如蒙特卡洛方法。    面试题剖析与解题思路:        我们将对一些著名的算法面试题进行深入剖析,例如:            二叉树的遍历(前序、中序、后序、层序)及其变种。            链表的反转、查找倒数第 k 个节点、合并两个有序链表。            数组中的最大子数组和、最长递增子序列。            动态规划解决的经典问题,如爬楼梯、打家劫舍。            图相关的面试题,如朋友圈问题、课程表(拓扑排序)。        重点讲解解题的思维过程:如何审题、如何分析问题、如何选择合适的数据结构和算法、如何编写清晰且高效的代码、如何进行测试和优化。  第四章:实战进阶与工程化思维  本章将进一步提升您的实战能力,着重于将算法知识与实际工程开发结合,培养解决复杂问题的工程化思维。     系统设计基础:        理解大型系统的基本组成部分,如负载均衡、数据库、缓存、消息队列等。        如何根据需求设计一个简单的系统,例如 URL 缩短服务、社交媒体feed流。        如何考虑系统的可伸缩性、可用性、一致性。    性能优化策略:        除了算法层面的优化,还将探讨代码层面的性能提升,如避免不必要的计算、合理使用内存、选择合适的库函数。        理解缓存机制(CPU 缓存、内存缓存、分布式缓存)对性能的影响。        学习使用性能分析工具(Profiler)来定位瓶颈。    调试与测试:        掌握高效的调试技巧,理解断点、单步执行、查看变量等。        理解单元测试、集成测试、端到端测试的重要性,以及如何编写有效的测试用例。    代码规范与可读性:        强调编写清晰、易读、易于维护的代码的重要性。        介绍常见的代码风格指南和设计模式(如单例模式、工厂模式)在实际开发中的应用。    学习资源与职业发展:        推荐更多优质的学习资源,如在线课程、技术博客、开源项目。        分享关于如何在技术领域持续学习和成长的建议。  通过本书的学习,您将不仅能够掌握算法与数据结构的核心知识,更重要的是能够将这些知识融会贯通,以严谨的逻辑思维、高效的算法设计和扎实的工程实践能力,应对各种技术挑战,在未来的职业生涯中脱颖而出。