百度AIG知识图谱部算法实习生面经(已拿offer)
一面:
1.自我介绍
2.平时用什么编程语言比较多
python,另外学过C语言和JAVA
3.c语言里指针占多少内存
答成8位了,应该根据机器而言是16位或32位
4.python里的map函数,讲一下它的作用和返回值
传入一个函数和一个list,将这个函数作用于这个list的每个元素上.返回值是一个新的list.
5.什么是梯度下降法
6.手写代码:归并两个有序数组
7.知不知道什么数据结构的查找的时间复杂度是O(1)
哈希表,也就是python中的dict
8.哈希表的原理是什么
利用哈希函数映射,构造出一个键值对
9.手写代码:两个大文件a和b,每一行存储的都是一个字符串,找出其中在两个文件中都出现过的字符串
构造一个哈希表,先逐行读入文件a,如果该字符串已经在哈希表中就跳过,如果不存在就存入哈希表中.读完以后逐行读入b,查找哈希表中有没有对应的值.
当时用的是dict,面试官说这种情况直接用set会更好.
10.如何判断一个链表中是不是存在环
一开始理解成是头尾相连的环,先回答了设头结点为一个特殊字符,比如'*',然后一直往下读取,如果读到null说明没有环,如果读到'*'说明有.
面试官提示说不一定是和头结点连成环,先回答了类似上面的想法,每一位设一个特殊字符,然后判断.但是需要用一个额外的空间来存储被设为特殊字符的结点原来的值.
面试官问有没有不需要额外空间的方法,思考了一会想到设立两个指针,都从头部开始遍历,一个指针每次前移一位,另一个指针每次前移两位,如果它们相遇就说明存在环,如果遇到null说明没有环.
面试官问为什么这种方法一定能够找到环.因为假设环的长度是K,前一个指针每次都会比后一个指针多走一步,那么让两个指针一直走下去,肯定会存在一个M,使得K是M的因数,并且两者在环内相遇.
11.有一个内存放不下的大文件,每一行存储的是一个数字,现在要随机从中取100个数字,怎么取比较好
先想到直接随机取一个数M,然后取M~M+100行的数.面试官说无法确定文件的大小,那么这个M也无法随机取.
这道题没有想到太好的思路,后来在网上也没有找到类似题的答案.
二面:
一面过后一天接到了二面的电话
1.自我介绍
2.知道c++中指针和引用的区别吗
我表示没有学过C++,只学过C
3.一个有序数组,现在将它从某个位置翻转后,如何查找其中的数字
翻转有序数组问题,首先有序联想到了二分查找.然后根据查找的情况修改一下判断条件即可.因为一个翻转有序数组从中间截断后,必定有一边是有序数组,另一边仍是翻转有序数组,那么问题就解决了.
4.一个有序数组,给定一个k,要将它第k位后的数字整体移到前面去,如何实现
先回答了最简单的方法,就是新建一个数组,先存入原数组第k位后的数字,再存入前k位数字.空间复杂度为O(n)
然后又想到一种方法,定义一个操作为翻转,可以通过不停地交换数组两边的元素实现.那么首先翻转数组的前k个数字,再翻转数组第k位后的数字,然后再将数组整个翻转一次就可以了.空间复杂度为O(1)
5.一个n步的台阶,每次可以走1步或2步,走完n步有多少种方法
动态规划问题,f(1)=1,f(2)=2,f(n)=f(n-1)+f(n-2)
6.实现斐波那契数列的时间复杂度是多少
上题的动态规划式子实际上就是斐波那契数列,递归实现的时间复杂度是O(2^n),非递归实现的时间复杂度是O(n)
7.如果有两个单词的组成完全相同,就称为同源单词.例如stop和post.现在有一个字典,如果找出其中所有的同源单词?
想到了trie树.假设都是小写字母的话,那么就构造一个26叉树代表26个小写字母.在将单词存入树中时,将它拆为按字典序排好的字母,例如stop就是头结点->o->p->s->t,然后将stop存入t结点中.类似的post也会被存在头结点->o->p->s->t结点中.这样遍历一次字典后只需要看树结点中有没有多个单词就能找到全部同源单词了.
面试官问如果一个单词很长的话怎么办,回答可以用哈希表存储每个字母的出现次数.但是这种方法适合用于判断两个单词是不是同源单词,不适合查找所有同源单词.
网上一种思路是先按字母数量排序,然后再存入字典树,比较快速.
8.k-means的原理
9.k-means是局部最优还是全局最优,为什么
局部最优.原因我回答的是因为k-means的最终结果和初始点的选取有关,所以不可能是全局最优的.
面试官表示应该从凸函数的角度去解释.另外在网上看到一种说法是k-means是贪心算法的一种实现,所以是局部最优.
10.项目经历
11.有2.5亿个数字,要从中找出所有只出现过一次的数字,如何实现
首先利用哈希表将2.5亿个数字划分成1000个小文件.然后对于每个小文件,采用bitmap的思想.所谓bitmap就是指用位来代替数字,本题数字可能有没出现过,出现过一次,出现过多次三种情况,所以要用2位来表示一个数字.在完成所有文件的bitmap后,00表示没有出现过,01表示出现过一次,10表示出现过多次,那么我们将1000个文件中每组对应的两位bitmap相加,如果一组结果为01就表示对应的数字只出现过一次.
offer流程:
过了一个周末后接到了部门经理的电话,给了口头offer
两天后接到HR电话,商量了入职时间.
又一周后收到了正式offer~
找算法岗实习的一些经验:
- 对你想做的方向(比如机器学习/计算机视觉/自然语言处理/深度学习)的常用算法的数学原理和编程实现要深入了解,很可能会被问到公式推导或者底层实现之类的细节.例如我是机器学习方向的,那么就要着重了解svm\决策树\nb\lr\knn\k-means这些算法,以及相关的损失函数和各种优化方法.推荐的书籍是《统计学习方法》
- 计算机专业的几门大课(计组,计网,操作系统,数据结构)尽可能掌握得扎实一点,其中对算法岗来说最重要的是数据结构与算法,推荐在leetcode或者类似的平台刷题,不用贪多,重要的是掌握几种常用数据结构和算法(数组,树,dfs,bfs,动态规划,哈希表)的应用场景.另外一定要了解常用数据结构操作和算法的时间复杂度.
- 算法岗和大数据是分不开的,面试中的最后一题很可能是关于处理海量数据的.可以参考教你如何迅速秒杀99%的海量数据处理面试题
- 对于常用的语言(c++,java,python中的一门或多门)要深入了解,不能局限于实现简单的代码逻辑.以python为例,要知道列表生成式\各种内置数据结构的原理\map函数\深浅拷贝这些知识.
- 会用一些相关的框架或库,例如数据处理的numpy和pandas,机器学习的sklearn和xgboost,深度学习的tensorflow/pytorch/keras等等.
- 最好有一些相关的竞赛(Kaggle,天池)或项目经历,既可以锻炼自己的工程能力,也会让面试的时候有自己擅长的东西可讲,否则就会被问到很多基础方面的问题.