前言
也是来自一位粉丝分享的面试教训
这位同学大三暑期实习,经验三个技术面加一个hr面上岸腾讯,面试官问的题也是蛮有代表性的,比拟考验原理和思维逻辑,整理出来给大伙看一下,近期有面试的同学倡议珍藏,很有帮忙。
面试通过
- 历经3技术+1hr,4轮面试
- 技术一面-----6.16
- 技术二面-----6.18
- 技术三面-----6.23
- hr面-----6.30
- oc-------7.1
- offer----7.2
面试题
所有的题这一篇文章必定是讲不完的,这里就挑一些比拟经典的题目跟大伙聊聊。
残缺的面试题能够看看我整顿的这份《2021腾讯Java岗面试真题》,
当然了,你对腾讯不感冒的话其余互联网top公司的真题我也有整顿,关注公众号:北游学Java,回复“面试”即可支付我整顿好的所有面试材料。
好了,不废话了,开始注释。
依照常规,我先把题贴出来,再提答案,能够本人先思考一下,不会的能够往下翻看答案。
- 深克隆、浅克隆,以及实现办法
- Java对象拜访
- 解决Hash抵触的办法,Hash抵触数据化
- equals和hashcode的关系
- Innodb为什么抉择B+树
- 思维题,天平称小球,在一堆轻的中找到一个重的,总结通用公式
- topk问题的场景题
- 算法局部:
①宰割回文串
②手写LRU,并讲述原理讲的底层一些,为什么应用双向链表
③ rand5()->rand7()
面试题解
1、深克隆、浅克隆,以及实现办法
浅克隆:对象的援用类型变量复制的是对象的援用值
深克隆:将援用类型变量所指向的对象内存空间也复制一份给新对象
如何实现对象的克隆?分三步:
- 对象的类实现Cloneable接口;
- 笼罩Object类的clone()办法;
- 在clone()办法中调用super.clone();
public class ShallowClone implements Cloneable{ public int id; public String name; public ShallowClone(int id, String name){ this.id = id; this.name = name; } public Object clone(){ Object sc = null; try { sc = super.clone(); } catch (Exception e) { System.out.println(e.toString()); } return sc; } public static void main(String[] args) { // TODO Auto-generated method stub ShallowClone sc1 = new ShallowClone(1, "sc1Name"); ShallowClone sc2 = (ShallowClone)sc1.clone(); System.out.println("sc1's id: " + sc1.id + "\tsc2's id: " + sc2.id); System.out.println("sc1's name: " + sc1.name + "\tsc2's name: " + sc2.name); System.out.println(sc1.name == sc2.name); System.out.println(sc1.name.equals(sc2.name)); }}
输入后果:
sc1's id: 1 sc2's id: 1sc1's name: sc1Name sc2's name: sc1Nametruetrue
2、Java对象拜访
句柄拜访形式:java堆中将划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中蕴含了对象实例数据和类型数据各自的具体地址信息。
指针拜访形式:reference变量中间接存储的就是对象的地址,而java堆对象一部分存储了对象实例数据,另外一部分存储了对象类型数据。
[图片上传失败...(image-68dcf6-1625474897121)]
这两种拜访对象的形式各有劣势,应用句柄拜访形式最大益处就是reference中存储的是稳固的句柄地址,在对象挪动时只须要扭转句柄中的实例数据指针,而reference不须要扭转。
应用指针拜访形式最大益处就是速度快,它节俭了一次指针定位的工夫开销,就虚拟机而言,它应用的是第二种形式(间接指针拜访)
3、解决Hash抵触的办法
尽管咱们不心愿发生冲突,但实际上发生冲突的可能性仍是存在的。当关键字值域远大于哈希表的长度,而且当时并不知道关键字的具体取值时。抵触就难免会发 生。
另外,当关键字的理论取值大于哈希表的长度时,而且表中已装满了记录,如果插入一个新记录,不仅发生冲突,而且还会产生溢出。解决抵触和溢出罕用的办法有两种
- 凋谢定址法
- 拉链法
具体就不开展讲了,不是一两句话能够讲完的,感兴趣的话能够本人找找相干的材料跟博客
4、equals和hashcode的关系
- 两个对象equals为true的话,hashcode也应该雷同
- 两个对象equals为false的话,hashcode最好也要不同,不然影响效率,话中有话就是重写equals的话举荐也重写hashcode
5、Innodb为什么抉择B+树
这题的话我提一下B+树的特点应该就好了解了
B+树特点:
- B+树每个节点能够蕴含更多的节点,这样做有两个起因,一个是升高树的高度。另外一个是将数据范畴变为多个区间,区间越多,数据检索越快。占用空间十分小,因而每一层的节点能索引到的数据范畴更加的广。换句话说,每次IO操作能够搜寻更多的数据。
- 每个节点不再只是存储一个key了,能够存储多个key。
- 非叶子节点存储key,叶子节点存储key和数据。
- 叶子节点两两指针互相链接,程序查问性能更高。叶子节点两两相连,合乎磁盘的预读个性。
6、思维题:天平称小球,在一堆轻的中找到一个重的,总结通用公式
这题也简略,用三分法很快就能够得出答案
- 每次将球分成三份(如果能平均分的话就平均分)。
- 将雷同数量的两份放天平上,如果两份一样重,则较轻的球必定在第三份中,接下来对第三份进行同1的操作;
- 否则,则对分量较轻的那一份进行同1操作。
所以,y<=3^x
7、topk问题的场景题
这个应该也算是面试中比拟常见的场景题了,网上的解答博客有很多,这里提一下,就不赘述了
8、算法局部:
①宰割回文串
这道题也算是力扣比拟经典的了,这里给大伙贴张图,应该就很好了解了
②手写LRU
package algorithm.Interview;import java.util.HashMap;public class LRUCache { private Node firstNode; private Node lastNode; private int initialCapacity; private HashMap<String, Node> hashMap; public LRUCache(int initialCapacity) { if (initialCapacity <= 0) { throw new IllegalArgumentException("initialCapacity must > 0"); } this.initialCapacity = initialCapacity; hashMap = new HashMap<>(); } public String get(String key) { Node node = hashMap.get(key); if (node == null) { return null; } //元素被查问,则挪动元素到链表尾部 removeNodeToTail(node); return node.value; } public void put(String key, String value) { Node node = hashMap.get(key); if (node == null) { //大于内存容量,须要删除最不罕用节点 if (hashMap.size() >= initialCapacity) { // 删除最不罕用的 String oldKey = removeNode(firstNode); hashMap.remove(oldKey); } Node newNode = new Node(key, value); addNode(newNode); hashMap.put(key, newNode); } else { node.value = value; //再次被赋值,挪动到链表尾部 removeNodeToTail(node); } } /** * 挪动元素到链表尾部 * @param node */ private void removeNodeToTail(Node node) { if (node == lastNode) { return; } //先删除 removeNode(node); //再增加到尾部 addNode(node); } /** * 尾插法,链表元素越靠前越旧 * @param node */ private void addNode(Node node) { if (lastNode != null) { lastNode.next = node; node.prev = lastNode; } //尾结点指向新插入的node lastNode = node; //链表为空,则同时为首节点 if (firstNode == null) { firstNode = node; } node.next = null; } /** * 移除指定元素,并返回移除元素的key * @param node * @return */ private String removeNode(Node node) { if (node == lastNode) { lastNode = lastNode.prev;//尾结点指向原尾结点的前驱节点 lastNode.next =null; } else if (node == firstNode) { firstNode = firstNode.next;//首结点指向原首结点的后继节点 firstNode.prev = null; } else { node.prev.next = node.next;//以后节点的前驱节点的后继节点指向以后节点的后继节点 node.next.prev = node.prev;//以后节点的后继节点的前驱节点指向以后节点的前驱节点 } return node.key; } private class Node { Node prev; //前驱节点 Node next; //后继节点 String key; String value; Node(String key, String value) { this.key = key; this.value = value; } } @Override public String toString() { StringBuilder ret = new StringBuilder(); Node p = firstNode; while (p!=null){ ret.append("key:").append(p.key).append(",value:").append(p.value).append("; "); p = p.next; } return ret.toString(); }}
③ rand5()->rand7()
算法代码:
public static int random5() { return (int) (1+Math.random()*5); } public static int random7() { int a=random5(); int b=random5(); int rand=10*a+b; if(rand<14) { return 1;//11 12 13 }else if(rand<22) { return 2;//14 15 21 }else if(rand<25) { return 3;//22 23 24 }else if(rand<33) { return 4;//25 31 32 }else if(rand<36) { return 5;//33 34 35 }else if(rand<44) { return 6;//41 42 43 }else if(rand<52) { return 7;//44 45 51 } else return random7();//52 53 54 55 }
测试代码:
public static void main(String[] args) { HashMap<Integer,Integer> map5=new HashMap<Integer,Integer>(); for(int i=0;i<10000000;i++) { int key = random5(); if(map5.get(key)==null) { map5.put(key, 1); }else map5.put(key, map5.get(key)+1); } System.out.println("random5:"); map5.entrySet().forEach(e->{ System.out.println(e+"\t"+1.0*e.getValue()/10000000); }); System.out.println(); HashMap<Integer,Integer> map7=new HashMap<Integer,Integer>(); for(int i=0;i<10000000;i++) { int key = random7(); if(map7.get(key)==null) { map7.put(key, 1); }else map7.put(key, map7.get(key)+1); } System.out.println("random7:"); map7.entrySet().forEach(e->{ System.out.println(e+"\t"+1.0*e.getValue()/10000000); }); }
好了,这篇文章就写到这把,除了下面说的这些题,还有一些对于TCP、线程池等题,问的挺宽的,毕竟面试造火箭嘛,篇幅所限这里就不贴出来了。
不过也别悲观,所有的题我都整顿成一本《2021腾讯Java岗面试真题》PDF了,前面也会继续收录最新面试题,间接点击就能够支付
除了腾讯之外其余大厂的真题我也在收集整理,都能够收费分享给大家,
须要的同学关注公众号:北游学Java,回复“面试”即可支付我整顿好的所有面试材料,还有海量的Java零碎学习材料哦!