mysql索引用trie树_腾讯Java后台开发面经(总共五面,附参考答案)

腾讯SNG

后台开发工程师

大概是8月初投的简历,当时没有选事业群,第二天直接被sng捞了,抓着我一顿面试。

一周内就面完了三次面试,接着就开始无尽的等待,整整等了三周左右,终于完成了四面和HR面。

整个过程还是比较曲折的,技术面试的难度也挺大的,不过他们部门也是Java线,所以还比较有的聊。结果目前还不知道。

一面:

1 有序数组排序,二分,复杂度

2 常见排序算法,说下快排过程,时间复杂度

首先设置一个标志位数字,一般选取第一个数作为标志,然后从右向左找到第一个比标志位小的数字,再从左向右找出第一个比标志位大的数字,两个数字交换位置,继续该过程,知直到左右两个方向的查找过程相遇,此时第一个标志位数字到达最终位置。接着以此位置为中间点,左右两部分数组分别递归执行该过程,最终即可完成快速排序。

时间复杂度是NlogN,因为递归栈的深度是LogN,并且需要执行N次。

空间复杂度是LogN,因为递归栈的深度是LogN。

3 有N个节点的满二叉树的高度。

1+logN

4 朋友之间的点对点关系用图维护,怎么判断两人是否是朋友,并查集,时间复杂度,过程。

该问题可以拆解为以下过程,其实就是建立并查集的过程。

初始化元素

实现元素与元素间的联合操作(设置元素的父节点)

实现查找元素所在树的根节点(一直往上找父节点,知道知道根节点)

判定两个元素是否在同一棵树上(如果根节点相同,那么它们自然是相连的)

5 单元点最短路的方法,时间复杂度

单元点最短路径问题可以使用迪杰斯特拉算法解决,这里就不赘述了。时间复杂度为O(N^2)

迪杰斯特拉算法

6 如何实现关键字输入提示,使用字典树,复杂度多少,有没有其他方案,答哈希,如果是中文呢,分词后建立字典树?

使用字典树是比较好的联想输入方案。

7 hashmap的实现讲一下吧,讲的很详细了。讲一下红黑树的结构,查询性能等。

hashmap基本上是Java面试必问的内容了。这里我把常见的考点都列举一下。

hashmap的数据结构:数组加链表的结构,hashmap类中会维护一个entry类型的数组,里面保存的是entry对象,entry对象包括key和value。

用户在添加一个键值对时,hashmap会首先计算key的hash值,并且通过该hash值&(数组长度-1)计算出一个index值,该inxdex值决定着该键值对会放在entry数组的哪个位置。

确定完键值对在数组的位置后,hashmap会判断该位置是否已经有元素或者是多个元素形成的链表,如果没有则直接放入,如果有则会遍历链表(对于1.8的hashmap来说,也可能是红黑树)如果能找到和自己key完全一样的键值对(通过equals方法判断)则替换掉该键值对,如果找不到key相同的,则插入到链表的尾部(不同版本hashmap的插入位置不同,我记得JDK1.7是头插法,1.8是尾插法)

JDK1.8对hashmap进行了一些优化,当某个数组位置上的链表长度超过8的时候,会优化成为一颗红黑树,所有结点变成树节点,这样既提高了查找效率也提高了插入的效率。所以1.8的hashmap相关方法也会随之调整,比如需要先判断一个节点是否是红黑树节点。

hashmap的扩容是2倍扩容,也就是数组变成原来的两倍长度,因此节点也需要进行位置调整,对于JDK1.7版本来说,需要对每个节点进行重哈希,然后重新插入到新的位置。而1.8版本优化了这一方式,它使用两个链表来串联两种不同类型的节点,区分的依据是,两种节点的hash值。

上述方法的原理是这样的:因为是两倍扩容,假如原数组长度是8,现在就变成16,对应的表长度-1用就是7和15,用二进制表示就是111和1111,而用hash值和这两个数相与的结果,区别也只会在最后一位,要么是0要么是1,所以只要判断相与结果最后一位是0还是1,即可判断它的位置需不需要改变,如果不需要,则连入第一个链表,如果需要,则连入第二个链表,最后在转移时重新放入合适的位置即可。

8 Java中的垃圾回收讲一下,讲了分代,gc算法,gc root可达性分析等

讲到垃圾回收,一般都需要讲到这么几点内容:

JVM的内存分区,包括虚拟机栈、程序计数器、堆区、方法区、本地方法栈。

堆区用于存放对象。

栈区用于执行方法,保存引用。

方法区用于保存类的元数据信息。

本地方法栈则用来执行本地方法。

程序计数器则是记录当前程序运行到哪里的一个指示器。

垃圾回收主要发生在堆区,有时候也会发生在方法区(full gc)

堆区又可以被分为年轻代和老年代。

年轻代又可以被分为eden区和survivor区。

年轻代发生的垃圾回收叫做young gc,一次YGC后剩余的对象会被转移到survivor区。

而survivor又可以分为from区和to区。刚刚说到进入survivor区就是进入from区。

接下来每次YGC后,都可能会有新的对象进入survivor区。

而survivor中的from和to区每一次都换交换角色,什么意思呢,就是比如第一轮ygc后from区有2个对象,to区有0个对象,第二轮ygc后from区的对象会被转移到to区,并且from区变为to区,to区变成from区。

这样做的原因是,每次对象转移都会更新对象自身的转移次数,一旦转移次数到达阈值,便会自动进入老年代。

老年代发生的gc叫major gc,一般由full gc触发,full gc包括young gc和major gc,并且还会回收方法区中的垃圾。

full gc有几种触发条件,使用system.gc()方法可能触发gc但不能保证执行。

一般当survivor区的对象无法晋升到老年代时会发生full gc,又或者大对象无法进入老年代时也会触发full gc。full gc会触发stop the world,导致应用停顿几秒。

垃圾回收算法一般包含停止复制、标记清除、分代回收等方法。分代垃圾回收的方法是指在年轻代使用停止复制算法,在老年代使用标记清除算法。

垃圾回收器有传统的串行垃圾回收器,以及并行垃圾回收器,并且有适用于年轻代和老年代的不同版本,另外也有注重吞吐量的垃圾回收器(要求服务线程执行的时间/垃圾回收线程执行时间 尽量大)以及注重停顿时间的垃圾回收器。

CMS垃圾回收器就是一个注重停顿时间的垃圾回收器。它的回收过程是这样的:

首先,标记GC ROOT,完成初始标记(这些被标记的对象不会清除)

然后,开始进行并发标记,gc线程和应用线程并发运行,不会出现长时间的停顿,但是吞吐量较低。

接着,stop the world,短暂地停顿,完成剩余的标记工作,必须要有一段时间的停顿才能最终完成正确的标记。

最后,并发清除剩余的垃圾。

另外我们还会用到的垃圾回收器G1,g1收集器和cms的收集方式类似,但是g1将堆内存划分成了大小相同的小块区域,并且将垃圾集中到一个区域,存活对象集中到另一个区域,然后进行收集,防止产生碎片,同时使分配方式更灵活,它还支持根据对象变化预测停顿时间,从而更好地帮用户解决延迟等问题。

9 讲一下两个项目你都做了什么把。

10 除了代码之外你还学习了什么技术,框架。

11 死锁是怎么产生的

死锁的四个必要条件。

12 线程和进程的区别

操作系统基本概念问题

13 进程的通信方式

线程通信和进程通信

线程通信一般只需要使用共享内存的方式即可实现。

而进程通信则需要额外的通信机制。

1 信号量,一般多进程间的同步使用信号量来完成,系统为临界区添加支持并发量为n的信号量,多进程访问临界区资源时,首先需要执行p操作来减少信号量,如果信号量等于0则操作失败,并且挂起进程,否则成功进入临界区执行。

当进程退出临界区时,执行v操作,将信号量加一,并唤醒挂起的进程进行操作。

2 管程,管程是对信号量的一个包装,避免使用信号量时出错。

3 管道,直接连接两个进程,一个进程写入管道,另一个进程可以读取管道,但是他不支持全双工,并且只能在父子进程间使用,所以局限性比较大

4 消息队列

操作系统维护一个消息队列,进程将消息写入队列中,其他进程轮询消息队列看是否有自己的消息,增加了轮询的开销,但是提高了消息的可靠性和易用性,同时支持了订阅消息。

5 socket

socket一般用于不同主机上的进程通信,双方通过ip和port的方式寻址到对方主机并找到监听该端口的进程,为了完成通信,他们先建立tcp连接,在此基础上交换数据,也就完成了进程间的通信。

14 CPU的执行方式

很奇怪的一个问题。

大概的思路是这样的:

计算机启动,cpu执行引导代码,加载操作系统到引导区

操作系统接手控制,执行特定程序,将程序代码装载到内存中,并将cpu的计数器指定到该内存位置,让cpu从当前位置开始执行代码。

15 代码中遇到进程阻塞,进程僵死,内存泄漏等情况怎么排查。

通过ps查询状态,分析dump文件等方式排查。

16 Linux了解么,查看进程状态ps,查看cpu状态 top。查看占用端口的进程号netstat grep

17 10g文件,只有2g内存,怎么查找文件中指定的字符串出现位置。MapReduce分割文件处理。

他说可以用cat | grep 管道处理。

18 Linux的swap了解么,完全不懂。

和内存分页有关,有兴趣的可以了解一下。

19 Redis和MySQL最大的区别

一个是内存数据库,一个是关系数据库(存储数据在磁盘中)

20 讲一下Tomcat的基本架构和组件,以及请求的整个流程。说了一下connector和container架构和servlet请求过程。

Tomcat的基本架构:

connector主要用于接收http请求和发送http响应。当http请求到来时,connector负责解析该请求,并且将请求重新封装,然后转发到container的入口servlet。

container中包含多层结构,最外层是engine,接着是host,然后是context,最后是wrapper,一个wrapper对应着一个servlet,每个http请求被指定的servlet处理,最后完成http的响应。

servlet是一个请求处理器,在请求到达servlet之前,可能要经过一系列的filter调用链,比如字符集过滤器,可以把把字符集设置为UTF-8。

21 MySQL的存储引擎,有什么区别。

简单来说,MySQL的myisam引擎是不支持聚簇索引、行级锁以及事务的,而innodb是支持这些特性的。

22 范围1到1000的数,原本有1000个,互不重复,现多出来1个重复的数,怎么找到他

统计次数后找出该数,面试官表示太慢,实际上答案是求和相减。

23 N个糖果,每次只能取1个到6个,不能不取,你先取,请问是否有必胜策略,怎么取。

刚开始说不太记得了,面试官提示了几个例子,找出规律不能为7的倍数,每次取到只剩7的倍数个糖果即可。

二面:

1 快排的时间复杂度,冒泡时间复杂度,快排是否稳定,快排的过程

2 100w个数,怎么找到前1000个最大的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值