ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

小米校招面经

2020-11-24 10:56:48  阅读:127  来源: 互联网

标签:一个 一下 面经 C++ 链表 线程 校招 小米 指针


前言

由于面试时候的问题和回答全都是后来凭着记忆写出的,因此难免会有遗漏。但大致的问题流程与实际面试时基本无二。这里记录下来,算是一个经验的分享与积累吧。

面试背景及准备

在这里插入图片描述
我投递的是C/C++的后台开发岗,大概是在20号左右投递的简历,三天后就收到了面试官的电话,当时收到电话但听不到对方的声音,还以为是打错了。挂掉后过了半分钟又收到了面试官的电话,告知我看了我的简历,问我有没有兴趣参加面试(这途中我的听筒声音断断续续,不知道是哪边的问题)。因为下午有一些急事,所以定了晚上七点的电话面。

面试官在电话里说会问一些关于C/C++的知识。因为不确定会不会考算法和数据结构,所以我就多嘴问了一下,得到的答复是可能会有涉及(后来想了一下,大概就是,如果前面语法部分答得还说得过去,就会往后深入问,不然甚至到不了问算法的环节就结束面试)。我紧接着问了会不会考TCP/IP相关,话刚问完,那边就挂了电话(同样不知道是哪边问题,当时心里慌得一批,以为是自己多嘴,面试官生气了)。

下午空闲下来,就塌下心开始准备。因为准备考研,很久没用C++做项目了,于是从12点一直准备到了下午七点,主要复习的就是C++的一些基本语法、细节以及特性。最后看了看自己简历上写的项目,复盘了一下代码。
这其间并没有准备什么数据结构和算法方面的知识。

电话面试所问的问题

1.自我介绍&语法基础

Q: 今天上午我们联系过了,现在你那边有时间吧(嗯嗯有的),那就先自我介绍一下吧。
A: 您好,我叫xxx,是一名来自北京建筑大学的大四学生,现在是一名共产党员。从大一开始我就爱上了编程,很享受项目在自己手里完成的那种成就感。大一刚开学四五个月,就自己动手实现了一些诸如2048、贪吃蛇之类的小游戏。后续也开发了一些小的项目,比如我简历里写的疫情期间全自动打卡系统,软件管理平台,Linux基于socket的多人聊天室等。因为现在已经大四,也要步入社会了,作为一名计算机系大学生,很渴望能到小米这样的好企业来发展。

Q: 好的,那就开始面试吧。我们先从简单的C/C++语法问起,后续再看看问点项目里的东西。你先来说一下C语言里struct和union的区别吧。
A: struct直白来讲就是实现了类似于C++里class的作用,里面可以定义一些成员属性和方法,以实现封装的操作。
Union我隐约记得是类似于一个字典,实现了从变量到某一值的映射。(后来发现自己这里记错了,当时还说的一本正经,真就是一本正经的胡说八道)

Q: 那你来说一下union和struct在计算占用内存上的方法吧。
A:union没了解关于计算内存的方法,所以不是太清楚。struct是根据对齐原则计算,比如结构体里有多个类型的变量,像int,char等,计算时的最终结果应该是struct中变量占用空间最大的内存的倍数。

Q:struct计算时有没有什么容易踩的坑呢?
A:…(沉默)
Q:比如计算含有多种不同数据类型的struct的时候,应该满足对齐原则。这地方你知道吗?
A:这部分我前面提到了…

Q:嗯嗯,那你有用过字节对齐吗?
A:(实话实说)没有。

Q:但我看你的简历里写你在Linux下做了一个socket编程的项目,socket编程就是需要用到字节对齐的,这部分怎么做的呢?
A:(实话实说)因为当时这个socket聊天室是Linux课设的一个选题,当时的时间非常短,只有两三天,为了赶进度,又想完成这个项目,我借鉴了书上部分固定的代码片段,因此这部分就没有深究。

Q:好的,那现在问一下C语言里的static,const吧。你先来说一下对static的理解。
A:static声明的数据是存放在C语言内存布局下的静态变量区的,它的作用域是局部、而生命周期是整个程序运行。static声明的静态局部变量,只有在第一次进入函数时会被初始化,例如我有一个函数function(),在函数中static int 了一个整型静态局部变量,function里每次将这个整型变量自增1,那么第二次调用function的时候,这个整型值就变成了2,第三次是3,以此类推。
static具有局部可见的性质,例如对于用static声明的静态全局变量,它的作用于就限制在了本文件,其他外部的程序想要用extern访问static声明的变量时,会报变量存在于另一文件的错误。
C++中的类里使用static只会被分配一次内存,不管使用这个类创建了多少个对象。

Q:OK,那谈一下const和define的区别吧。
A:(思考…)
我先来说一下C中程序执行的过程吧:预处理、编译、汇编、链接。define是用来做宏定义的,用define声明的宏就是在预处理阶段被替换,这个阶段编译器同时会做一下诸如删除注释之类的操作。而const声明的变量则是在编译阶段被编译的。大概就是这样。

Q:你说的没错,但不是最主要的,区别主要有两个,你说的算一个,另一个我提醒一下吧,define和const,是否都要类型检查呢?
A:(恍然大悟)#define只是简单的字符串替换,没有类型检查。而const是要进行判断的。

Q:那你知道const在编译阶段会被编译成什么汇编代码吗?
A:不知道,没涉及过。

Q:好的,接着说一下C语言和C++的区别吧。
A:我觉得这其中最大区别就是:C语言是面向过程的,比如完成一件事需要几步,需要几种方法,把这些方法对应写成函数。
C++是面向对象的,例如有一个物体,它具有一些属性和操作,我们就可以把这个物体的所有属性和方法进行封装,变成一个整体,对这个类的操作就更好的体现了结构性。


2.面向对象程序设计

Q:既然说到了面向对象,来说说面向对象的几大特点吧。
A:面向对象的特点有:封装性,继承以及多态。封装性就是前面提到的,将一个物体的属性和方法封装成一个整体。继承就是指,例如我们有好几种图形,分别是三角形,四边形,五边形等,而这些不同形状的本质都是多边形,我们就可以创建一个多边形的基类,让这些多边形都作为基类的派生类,继承基类的属性。
关于多态,其实就是用创建的基类指针去指向派生类的对象,对基类指针方法的访问就可以达到调用派生类对应的函数的目的。

Q:嗯嗯,多态的实现方法有什么呢?
A:我只知道可以通过virtual实现多态,其他记不太清楚了。

Q:既然提到了virtual,你来说一下virtual是什么吧。
A:virtual用于声明虚函数,虚基类。如果没有将基类中的函数声明为virtual的话,就算用基类的指针去指向派生类,调用派生类的方法,最后运行的结果也全都只会是基类的。这是因为静态链接(静态绑定)的原因,也就是说函数调用在程序执行前就准备好了。
使用了virtual之后,会告诉编译器不要静态链接到定义的虚函数,也就实现了动态绑定。

Q:好的,你说的是动态实现多态。还有一个静态的方法,能说一说吗。(这里我记不起来了,面试官接着说:)实现多态还有一种方法,就是重载,这个你来简单说一下吧。
A:重载就是可以声明几个具有不同参数列表(例如参数的类型,个数,顺序不同)的同名函数,这些函数可以实现不同的功能。

Q:可以把一个函数重载成多个,重载多个函数的区别是什么呢?
A:参数类型、个数、顺序都可以不同。

Q:如果只是返回值不同可以吗?
A:不行


3.计算机网络及内存管理

Q:tcp三次握手了解吗,来简单说一下握手的过程。
A:tcp的三次握手过程是这样的:有一个发送端,一个接收端。发送端想要发送数据给接收端,就需要发送一个sychronize的报文,代表“我给你发送消息了”。接收端接受到后,会发送sychronize/acknowledge的报文,代表“我接受到了你的报文”。发送端接收后,会接着返回一个报文,代表“我知道你知道我发送了”。

Q:嗯,那你说一下指针和引用的区别吧。
A:先说一下最本质的区别。指针的本质就是一个特殊的变量,它存放的是地址,指向一个存储单元;而引用其实就是原变量的一个别名,和原本的变量实际上就是同一个东西。

Q:C语言里对内存进行处理的函数都用过哪些。
A:分配用的malloc,释放使用的free。malloc是在堆上分配连续内存给用户,若想扩大malloc初始分配的内存,需要重新给用户分配一个满足要求大小的连续内存区。

Q:malloc以及包括new都会导致一些安全问题,C++11里引入了什么数据结构或者数据类型,可以解决这种安全问题,你知道吗?
A:不太清楚

Q:智能指针可以解决这个问题,你有了解吗。
A:(恍然大悟)听说过,但没用过。

Q:malloc底层实现了解吗,Linux内核上分配空间的函数有什么呢?
A:没接触过,不是很了解。


4.操作系统

Q:内核上有kmalloc和vmalloc,你既然没接触过,那后面应该也就不清楚了。看你简历上CSDN博客里有一些算法和数据结构的知识,你也是学计算机的吧,我也是计算机科学与技术的。那我们就聊一下操作系统相关的知识吧。先来简单说一下进程和线程吧。
A:进程是资源分配和调度的基本单位,线程是程序运行的基本单位。一个进程可以创建多个线程,这些线程共享该进程的内存空间,且每个线程之间有独立的堆栈。引入线程之后,程序的并发性就进一步提高了,可以说线程比进程有更好的并发性。

Q:好的,那来说一下进程通信的方法都有哪些。
A:管道pipe,消息队列,共享内存。共享内存就是…
Q:(打断)不用展开说这部分,你说的是其中三种,应该还有其他方式,是什么呢?
A:记不太清了。
Q:管道分为两种,有名管道和无名管道,这两种的特点和实现方式说一下吧。
A:也记不得了,不好意思。

Q:我来提醒一下吧,有一种通信方式是信号量机制,可以实现同步和互斥(我心里:最近考研复习的就是这个,一拍脑袋恍然大悟),进程的同步互斥可以通过信号量机制实现,那么线程是否也有相应的实现方式呢?
A:(想了半天)我记得有个管程,是可以实现对同步互斥进行封装,使得程序员可以更便捷的操作线程。
Q:管程…我没听说过,是不是你编的我也不知道(我…),纤程是可以实现管理线程的,这个了解吗?
A:听说过,但没用过。


5.数据结构和算法设计

Q:好的,我看你简历上面写的博客,里面涉及一些算法题,我就拿这考考你吧。回文串判定的算法,简单说一下吧。
A:可以设置双指针分别指向串的首尾,类似于火车碰头问题,两侧向中间依次遍历并检查所比较的当前元素是否相等,若循环直至碰头,代表是回文串,中间停止则不是。
还有一种方法,可以设置一个栈,将回文串入栈,利用栈后进先出的特性与原串弹出比较。

Q:接着说一下水仙花数的判定吧。
A:不好意思,太久不做OJ,记不得什么是水仙花数了。
Q:(水仙花数类似于回文串判定,只不过是一个整体)你那会说的算法并不是判断回文串的最好算法,会有冗余的串,还能想到其他的吗。
A:效率高的那个算法不太记得了,我能想到的暂时只有一种暴力的方法,也就是依次除十取余,商零为止。再将取到的位数放入数组或者串存储,最后利用上面提到的回文串判断算法进行判断。

Q:说一下单链表和双向链表的各自特点和对比。
A:单链表只有一个next指针用于指向下一个节点,双联表附设了一个prior指针指向前驱节点,这样单链表在删除一个元素时,就需要设置前驱指针pre来判断pre->next是否等于要删除的节点,若是,则将pre->next指向下一个节点。而双向链表由于有pre指针,就无需如此。
单项链表由于单向的性质,只能从链表的头结点开始依次向后遍历访问。双向链表则可以附设一个指针指向链表尾部,从而达到从后向前遍历的目的。
举个例子,同样是访问倒数第二个元素。用单链表实现时,一种比较好的方法是,需要使用双指针,让一个指针从链表头开始遍历,一个从链表的第二个节点开始遍历,这样当前面的指针走到末尾时,后面的指针就指向了倒数第二个节点。
但对于双向链表来说,一旦保存了尾指针,只需要通过prior进行访问倒数第二个元素。

Q:那如果我想要判断单链表是否有环,请你设计一个算法吧。
A:(思考了10秒),可以使用快慢指针的方法,设置快慢指针均指向头结点。一个慢指针一次走一步,另一个快指针一次性走两步,如果快指针始终未指向NULL,且快慢指针最终相遇,就代表单链表是有环的。如果快指针走到了NULL但未和满指针相遇,证明无环。

Q:没错。那C++STL知道吗,全称是什么?
A:到嘴边就是想不起来了。(思考6秒)哦对,是标准模板。
Q:你用到过哪些呢?
A:vector,set,map都用过。

Q:vector都有哪几种数据结构呢?
A:顺序表:线性表,链表。其他不知道了。

Q:set里元素是递增的?递减的?还是无序的?
A:递增的,且唯一,例如1这个元素,在set里只能出现一次。

Q:对,map里面有个特殊的,叫做hash_map,hash_map有几种解决哈希冲突的方法,简单说一下。
A:(说了线性探测再散列,还有平方探测。)

Q:map的底层实现用的什么数据结构呢?
A:(想了想)红黑树。

Q:红黑树的原理知道吗?
A:没用过,不知道。

Q:那你知道平衡二叉树吗,说一下。
A:平衡二叉树的每个节点的左右子树高度差的绝对值不超过1,这样递归定义每个节点就构成了平衡二叉树。


Q:好的,我们现在进入项目环节。你说的第一个项目用到了python+selenium,这里selenium是一个库吗?
A:是的,是用于实现自动化的一个库,可以模拟用户的真实操作,例如点击button等。
Q:说一下原理吧。
A:我们登录网页就可以查看网站web的源代码。selenium先是会加载一个浏览器的驱动,比如我这里使用的就是Firefox的驱动,加载了驱动后就可以模拟用户手动打开浏览器。之后是定位元素,举个例子,selenium通过一个button的id或者class定位到这个button,并通过调用find_element_by_id().click()的方式点击提交。

Q:你这个应该只是基于静态页面吧,如何处理动态页面的一些反爬和防注入的手段,导致没办法爬取的问题呢?这个有做过吗?

A:有的。我的这个疫情期间自动打卡项目中有一个id的定位就是一直不成功,后来我同时打开两个页面的源代码进行对比,发现相同button的id均具有相同前缀fs_tab_,但后缀不同,这些后缀可能是MD5码,也可能是随机生成的。通过分析发现,可以使用模糊匹配的方式定位到这个button,而不必全串匹配,实现了防止反爬的手段。

Q:你提到了模糊匹配,那应该用到了正则表达式吧。
A:并没有,这里的selenium提供了现成的start_with方法,可以实现模糊匹配。
对了,我之前还做过一个项目,是爬取一个动漫网站的,那个网站通过反爬手段,使得我爬取的照片链接总是失效的。后来想到了一种解决方案,也就是通过Python库函数进行截屏,因为漫画出现的区域是固定的,这样通过裁剪指定区域就可以实现图片的获取了。

Q:好的,面试到现在也快一个小时了,也差不多该结束了。咱们随便聊一聊吧。我现在在小米做的是相机工程师。你在这之前签了其他公司吗?
A:没有。

Q:(有些惊讶)那拿到了多少个offer了?
A:没拿到过,小米是面试的第一家。

Q:(十分惊讶)你们现在不应该是…
A:我是准备了考研的,但是觉得如果本科毕业就能来到小米这样的好公司,就暂时不读研了。我很喜欢小米的企业文化,相比某为这些公司就很人性化,很让人舒服。当然,如果没能成功拿到offer的话,我就去读研,目标是北京邮电大学。

Q:确实,但其实来小米工作三年,和那些研究生上了三年学最后出来找到的工作是基本一样的,而且你能在小米工作三年,可能比研究生读完出来的发展还要好。

Q:最后,你有什么想问的吗?
因为看到网上经验贴说一定要问点什么,我就问了小米手机部的历史,发展前景。
面试官也和我聊了聊自己的工作,我告诉面试官自己对小米有一种情结,第一部智能手机就是小米的“小米1S”,现在用的手机是小米的“红米K30PRO”,感慨了一下现在手机相机防抖算法和高焦距下画质处理的快速发展。

最后面试官告诉我hr会在两三天内联系我,让我做好准备。

标签:一个,一下,面经,C++,链表,线程,校招,小米,指针
来源: https://blog.csdn.net/cprimesplus/article/details/110039194

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有