前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >双非小伙暑期实习斩获腾讯WXG offer,这不比博人传燃?

双非小伙暑期实习斩获腾讯WXG offer,这不比博人传燃?

原创
作者头像
北游
修改2021-07-05 18:07:17
6110
修改2021-07-05 18:07:17
举报
文章被收录于专栏:一头扎进Java一头扎进Java

前言

也是来自一位粉丝分享的面试经验

这位同学大三暑期实习,经历三个技术面加一个hr面上岸腾讯,面试官问的题也是蛮有代表性的,比较考验原理和思维逻辑,整理出来给大伙看一下,近期有面试的同学建议收藏,很有帮助。

image
image

面试经过

image
image
  • 历经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、深克隆、浅克隆,以及实现方法

浅克隆:对象的引用类型变量复制的是对象的引用值

深克隆:将引用类型变量所指向的对象内存空间也复制一份给新对象

如何实现对象的克隆?分三步:

  1. 对象的类实现Cloneable接口;
  2. 覆盖Object类的clone()方法;
  3. 在clone()方法中调用super.clone();
代码语言:txt
复制
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));
	}
}

输出结果:

代码语言:txt
复制
sc1's id: 1	sc2's id: 1
sc1's name: sc1Name	sc2's name: sc1Name
true
true

2、Java对象访问

句柄访问方式:java堆中将划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。

image
image

指针访问方式: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+树特点:

  1. B+树每个节点可以包含更多的节点,这样做有两个原因,一个是降低树的高度。另外一个是将数据范围变为多个区间,区间越多,数据检索越快。占用空间非常小,因此每一层的节点能索引到的数据范围更加的广。换句话说,每次IO操作可以搜索更多的数据。
  2. 每个节点不再只是存储一个key了,可以存储多个key。
  3. 非叶子节点存储key,叶子节点存储key和数据。
  4. 叶子节点两两指针相互链接,顺序查询性能更高。叶子节点两两相连,符合磁盘的预读特性。

6、思维题:天平称小球,在一堆轻的中找到一个重的,总结通用公式

这题也简单,用三分法很快就可以得出答案

  1. 每次将球分成三份(如果能平均分的话就平均分)。
  2. 将相同数量的两份放天平上,如果两份一样重,则较轻的球肯定在第三份中,接下来对第三份进行同1的操作;
  3. 否则,则对重量较轻的那一份进行同1操作。

所以,y<=3^x

7、topk问题的场景题

这个应该也算是面试中比较常见的场景题了,网上的解答博客有很多,这里提一下,就不赘述了

8、算法部分:

①分割回文串

这道题也算是力扣比较经典的了,这里给大伙贴张图,应该就很好理解了

image
image

②手写LRU

代码语言:txt
复制
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()

算法代码:

代码语言:txt
复制
	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
	}

测试代码:

代码语言:txt
复制
	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系统学习资料哦!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 面试经过
  • 面试题
  • 面试题解
  • 1、深克隆、浅克隆,以及实现方法
  • 2、Java对象访问
  • 3、解决Hash冲突的方法
  • 4、equals和hashcode的关系
  • 5、Innodb为什么选择B+树
  • 6、思维题:天平称小球,在一堆轻的中找到一个重的,总结通用公式
  • 7、topk问题的场景题
  • 8、算法部分:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档