记蚂蚁金服前端第一次电面(校招)

这是我结合蚂蚁金服前端一面的经历整理的一些笔记。如果有什么不对的地方,欢迎大家指出。

关于这次面试相关的技术方面的问题我整理在了另外一篇文章里

前面的问题主要是对整个人的了解,后面技术方面的问题会根据前面这些问题的回答来问,所以前面的问题可以只说自己最擅长的内容,这样可以引导面试官往这些方面问(实际上面试官自己也会选面试者擅长方面的问题去问)。

1. 自我介绍

我就简单介绍了自己的学校和专业。

2. 介绍自己的项目和学的课程

我自己的话,项目就主要是课设了。
然后学的课程我就大概讲了一下有硬件、软件、前端、后台这些。

3. 为什么选择前端

我主要是因为当时选方向的时候,觉得前端入门容易,就选择了前端(入门容易这个当时面试没说)。另外一点就是前端“所见即所得”这个点也蛮吸引我的。

4.介绍自己前端的项目

这个问题和第2个问题有些类似,我的回答也差不多,不过举了最近一次前端有关的课设做例子。

5.介绍自己学的语言

我按学的时间讲了一下,有C++、JAVA、数据库语言、前端的HTML+CSS+JS、struts2和hibernate框架。硬件语言也有学一点,不过我没说了。

6.有无参加编程算法的项目或者比赛

这个我没有参加,就跳过了。感觉这个应该会是加分项,如果有参加,面试官应该会深入去聊这个。

7.对基础算法的了解,例如排序算法

这里我说了一下自己熟悉的冒泡排序和插入排序。

接下来就慢慢过渡到技术方面的问题了

8.讲一下快速排序

这个我当时忘记了,没有答出来,就跳过了。

它的基本思想是

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,以此达到整个数据变成有序序列。

快速排序的图示,来自百度百科
首先是第一趟排序(第一次划分):
要把比第一个数49小的数放到这个49的左边,剩下的放到右边。
1、从右往左找比49小的数,第一个是27,然后27和49调换位置,
变成27、38、65、97、76、13、49、49
2、从左往右找比49大的数,第一个是65,然后65和49调换位置,
变成27、38、49、97、76、13、65、49
之后就是上面两步操作的循环,
变成27、38、13、97、76、49、65、49
变成27、38、13、49、76、97、65、49
第一趟排序完成

接着将数据分成49左边和49右边两个部分,分别对两个部分进行上述操作,先进行左边部分排序,
变成13、27、38、49、76、97、65、49
此时左边部分已经不能再继续分组了,也就是说左边部分排序完成

然后进行右边部分的排序,也是按照上述操作,
变成13、27、38、49、49、65、76、97
右边第一趟排序完成

之后的以此类推,
变成13、27、38、49、49、65、76、97
排序结束

其实这种算法题,我觉得如果是远程面试,不是太方便去讲思路。
如果是面对面面试或者笔试的话,有纸和笔会好一点。

9.讲一下冒泡排序

因为我之前快速排序没回答上来,面试官就让我讲了我之前提到过的冒泡排序。

我当时的回答是冒泡排序就是每个数和相邻的数比较大小,这样大的数会很快沉到底下,小的数会上来。

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素已经排序完成。
这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

冒泡排序算法的原理如下:
1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2、对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3、针对所有的元素重复以上的步骤,除了最后一个。
4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

举例说明:6、3、8、2、9、1
第一趟排序:
1、6和3比较,6大于3,交换位置: 3 6 8 2 9 1
2、6和8比较,6小于8,不交换位置 3 6 8 2 9 1
3、8和2比较,8大于2,交换位置: 3 6 2 8 9 1
4、8和9比较,8小于9,不交换位置 3 6 2 8 9 1
5、9和1比较:9大于1,交换位置: 3 6 2 8 1 9
第一趟进行了5次比较, 排序结果: 3 6 2 8 1 9

第二趟排序:
1、3和6比较,3小于6,不交换位置 3 6 2 8 1 9
2、6和2比较,6大于2,交换位置: 3 2 6 8 1 9
3、6和8比较,6大于8,不交换位置 3 2 6 8 1 9
4、8和1比较,8大于1,交换位置: 3 2 6 1 8 9
第二趟进行了4次比较, 排序结果: 3 2 6 1 8 9

第三趟排序:
1、3和2比较,3大于2,交换位置: 2 3 6 1 8 9
2、3和6比较,3小于6,不交换位置 2 3 6 1 8 9
3、6和1比较,6大于1,交换位置: 2 3 1 6 8 9
第三趟进行了3次比较, 排序结果: 2 3 1 6 8 9

第四趟排序:
1、2和3比较,2小于3,不交换位置 2 3 1 6 8 9
2、3和1比较,3大于1,交换位置: 2 1 3 6 8 9
第四趟进行了2次比较, 排序结果: 2 1 3 6 8 9

第五趟排序:
1、2和1比较,2大于1,交换位置: 1 2 3 6 8 9
第五趟进行了1次比较, 排序结果: 1 2 3 6 8 9

最终结果:1 2 3 6 8 9

10.讲一下冒泡排序的(时间)复杂度

这个我当时忘记了,没有答出来,就跳过了。

若 n 个数据的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数 C 达到最小值: C m i n = n − 1 C_{min} = n-1 Cmin=n1
所以,冒泡排序最好的时间复杂度为 O(n) 。

若 n 个数据是反序的,需要进行 n-1 趟排序。每趟排序要进行 n-i 次关键字的比较(1≤i≤n-1)。在这种情况下,比较次数 C 达到最大值:
C m a x = ( n − 1 ) + ( n − 2 ) + ⋅ ⋅ ⋅ + 1 = n ( n − 1 ) 2 = O ( n 2 ) C_{max} = (n-1) + (n-2) +···+1=\frac{n(n-1)}{2}=O(n^2) Cmax=(n1)+(n2)++1=2n(n1)=O(n2)
冒泡排序的最坏时间复杂度为 O(n^2) 。

综上,因此冒泡排序总的平均时间复杂度为 O(n^2) 。

11.讲一下二分查找

我当时的回答是在一个有序数组里,首先将数组最中间的数和目的数比较,如果中间数比较大,就选择前半部分,然后将前半部分最中间的数和目的数比较,以此类推。

二分查找的查找过程:

首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

二分查找的图示
首先找到数组最中间的数45(若最中间的数有两个,则取前面那一个),与目的数47比较,目的数较大,则进一步查找后半部分(47-99),中间数81与47比较,目的数较小,则查找前半部分(47-53),中间数47与47比较,与目的数相等,则查找成功。

12.学过二叉树吗,讲一下广度遍历

我当时回答学过二叉树,但是不记得广度遍历了,然后提了一下前序遍历,面试官就跳过这个问题问我前序遍历了。

广度遍历的基本思想:

1、从图中某个顶点V0出发,并访问此顶点;
2、从V0出发,访问V0的各个未曾访问的邻接点W1,W2,…,Wk;然后,依次从W1,W2,…,Wk出发访问各自未被访问的邻接点;
3、重复步骤2,直到全部顶点都被访问为止。

广度遍历的图示
访问顺序为:0,2,1,5,3,4
结果不是唯一的,只要满足“广度”的含义即可。

12.那讲一下前序遍历

我当时记的有点混乱,就回答了先访问左结点,然后访问根结点,再访问右结点。(面试之后才发现我回答错了,回答成了中序遍历)

前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。

前序遍历的图示,来自百度百科
前序遍历结果:ABDECF

13.如何找到一个字符串里出现次数最多的字符

我的回答是先创建一个对象去存储字符串里每个字符出现的次数,用对象的属性名key储存每个字符,用对象的属性值value储存对应字符的出现次数。例如第一个字符是1,则创建一个 ‘1’ : 1,第二个字符是2,则创建一个 ‘2’ : 1,若之后出现1,则 ‘1’ : 1+1。最后再比较那些属性值value的大小,然后反过来通过最大的那个value找出对应的key,找到对应的字符。
比较属性值value的大小的话,就是先遍历对象,把那些value一个个放到一个数组里,然后排序比较。
如果字符串里有特殊字符,例如制表符、换行符、中文、各种符号,我当时回答是可以用转义符斜杠 \ ,但是面试官追问了一下,我就回答不上来了。

面试之后我百度了相关的问题,没想到用对象处理这个方式还是蛮普遍的。
特殊字符的问题,我暂时还没找到解决方法,问了师兄说可以试试用对应的编码,这个思路应该OK,但是不知道具体实施可不可行。

14.截取一个数的小数点后N位

这里我有点表述不清,具体的问题是:
有一个带有小数点的数,整数部分不清楚有多少位,要取到这个数的小数点后N位,也就是说后N位之后的部分直接舍去,不用四舍五入,输出前面的部分。例如取到123.123456789的后5位,就是舍去“6789”,输出123.12345。

我一开始理解错了,以为是要取小数点后的第N位上的数字。例如取123.123456789的第5位,也就是5。然后我回答先把这个数转换为字符串,然后用正则表达式取出小数点后面的部分,再用 charAt() 方法取出第N位上的数字。当时忘记了 charAt() 的名字,只记得有这个方法,答不出名字,蛮尴尬的。

如果是取前N位的话,我回答是先把这个数转换为字符串,然后用正则表达式分别取出小数点前面和后面的部分,也就是分开整数部分和小数部分,然后删去小数点后N位(这里我当时没想好具体怎么删去,所以讲的比较模糊),再用 concat() 方法连接之前被取出的整数部分和处理之后的小数部分( concat() 的名字我当时也忘了,手动捂脸),得到结果。

关于取第N位和取前N位,我暂时还没百度到比较符合题意的方法(大部分都是四舍五入的),这里我就讲一下我面试之后想到的一些方法吧。

取第N位的话,我上面讲的那个方法应该是可以的,另外一个应该可行的方法也是先把数转换为字符串,然后用 indexOf() 方法得到小数点的索引,也就是位置,再+N,就是第N位上数字的索引,再用 charAt() 方法取出第N位上的数字。这个方法和之前那个方法差不多,只是中间的处理不一样。

取前N位的话,我一开始想到一个很笨的方法,就是先用 toFixed() 方法(这个方法会四舍五入),得到要求的数字,然后用之前讲的方法得到小数点第N+1位的数字,通过这个数字是否大于4判断 toFixed() 方法有没“五入”进1,如果进1了再减去。
其实还可以把数字转换成字符串,再用正则表达式取出要求的数字,或者再得到要求的数字加上整数部分一共多少位(可以用之前取第N位的 indexOf() 方法),然后用 substring() 方法取出要求的数字。

15.讲一下浏览器的同源策略

页面的地址(源)是由协议、域名和端口组成,三个有一个不同的话,则不能互相进行访问,只能访问同源的资源。

16.讲一下跨域访问的解决方案

这个我不太懂,就跳过了。
跨域解决方案和上面的同源策略我都不是太了解,具体的我就没有放上来了,大家自行百度吧。

17.讲一下浏览器的事件模型

一个事件是从window到window的过程。
先是捕获,从window到DOM到body再一直往下到最底下的元素,捕获到目标之后就是冒泡,从最底下那个元素一直到最上面的window。
事件模型图示
一个完整的JS事件流是从window开始,最后回到window的一个过程。
事件流被分为三个阶段(1~ 3)捕获过程、(3~ 4)目标过程、(4~ 7)冒泡过程。

18.比较对象是否相等

我当时回答可以用双等号 == 去比较,如果双等号的两边数据类型不一样,会先对数据类型进行强制转换。

但是其实用双等号 == 去比较对象是错误的,因为基本类型 string,number 通过值来比较,而对象通过指针指向的地址来做比较。也就是说双等号 == 比较的是地址(三等号 === 也是),如果比较的对象地址不同,无论使用" == “还是” === ",都返回false。
另外,如果想比较对象是否相等,要先考虑是想判断两个对象的属性是否相同,还是想判断属性对应的值是否相同,如果是判断属性的值是否相等,还要考虑值是否为对象的情况。
下面讲一个判断对象的值是否相等的方法(值不为对象)

function isObjectValueEqual(a, b) {   
    //取对象a和b的属性名
    var aProps = Object.getOwnPropertyNames(a);
    var bProps = Object.getOwnPropertyNames(b);
    
    //判断属性名的length是否一致
    if (aProps.length != bProps.length) {
        return false;
    }
    
    //循环取出属性名,再判断属性值是否一致
    for (var i = 0; i < aProps.length; i++) {
        var propName = aProps[i];
        if (a[propName] !== b[propName]) {
            return false;
        }
    }
    return true;
}

19.讲一下js的this指针

这里我当时不知道面试官讲的是 this,而且我当时对js没有没有指针太确切的概念,就跳过了。

在JavaScript中,this指针是在创建函数时,由系统默认生成的两个隐式参数之一(另一个是arguments)。它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。this指针指向与该函数调用进行隐式关联的一个对象,该对象被称为“函数上下文”(相当于函数的参数)。

this在js中主要有四种用法:
1、作为普通函数使用:this指针指向window对象。
2、作为对象方法来使用:this指针指向该方法的所有者(对象)。
3、call()和apply()方法调用:this指针指向call与apply方法指定的对象。
4、作为构造函数来使用:this指针指向new关键字创建的新对象。

20.讲一下CSS盒模型

盒模型分为标准盒模型和IE盒模型,盒模型由内容content、内边距padding、边框border和外边距margin组成。
标准盒模型(元素)的宽width、高height就是内容content的宽、高。
IE盒模型(元素)的宽width、高height是内容content、内边距padding加边框border。

21.Vue、React这些框架有接触吗

这些框架我都还没怎么学习,就跳过了。

这里开始问的就是一些比较个人的一些问题了,我觉得可能是面试官没想到什么技术方面的问题想问的了。

22.通过什么方式学习前端和其他知识

我的话一个是通过课程的学习,另一个是自己平时的自学,比如说看网上教程。

23.会关注一些最新的前沿的技术、框架之类的吗

我的话有时候会,看这些跟自己有没关系,如果自己有相关的了解,就会多关注一点,如果自己完全没有相关的了解的话,会不怎么关注。

24.通过什么渠道去获取这些信息

我的话一个是微信公众号,另外有时候老师上课会提到,还有就是学习网上教程的时候会看到。

25.看到之后会去了解这些东西的内容吗

我的话如果是跟自己有关的或者自己感兴趣的会去多了解一点。

26.之前有没哪些内容是通过这些方式去得到的

我的话有的,只不过这些内容不算太新颖的了。就好像我之前学习前端的时候,发现有些网站是把那些小图片图标放在一个大图片里,这种叫雪碧图或者精灵图,这个是为了提高性能,减少HTTP的请求。还有一个跟图片有关的就是SVG格式的图片,可以用代码做出来,它是矢量图形,所以放大缩小是无损的。

27.用过git吗

这个git我还没接触过,就跳过了。

中间还有一个问题没听懂就跳过了

28.有没什么想问的

这个是面试官已经面试结束了,问一下我这边还有没什么疑问。
(后记:其实一般来说,面试官提这个问题,主要是希望面试者问一些和本公司或者本部门相关的具体问题,比如说工作内容等等,如果是HR的话则是薪资或者福利这些,这样能看出面试者对本公司本部门的了解有多少。)
我问了一个面试之前准备过的问题,感觉面试官对这个问题也应该会有蛮多想说的。
Q:对于Vue和React这两个现在比较热门的框架,更推荐哪一个
A:这个没有什么更推荐的,这两个都是属于MVVM(Model-View-ViewModel即模型-视图-视图模型),只不过两者作者的思路和实现的方式不一样。Vue是数据双向绑定的,所以可能很多产品用起来会方便一点。React则是单向数据流,有些限制可能多一点,但是也能满足项目。这个看个人的喜欢和项目的定位。从社区来说,两者的社区都很好,不过因为Vue的作者是谷歌的中国人,所以国内来说可能Vue用的会多一点,其实两个社区差不多,只是Vue的中文资料可能多一点,React的英文资料多一点。总之,两个都可以,没有更推荐的。

总的来说,我这次面试还是太紧张了,有时候说话还是会有磕磕绊绊,一方面也是因为技术不足,想不到什么可以说的。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值