面经(2)
腾讯面经
1. 自我介绍与项目
在自我介绍环节,建议突出以下几点:
- 背景和教育经历:说明你的专业、学校和毕业时间。如果有相关的学术成果或者奖项也可以提及。
- 实习和项目经验:重点介绍和面试岗位高度相关的实习或项目经历。比如,可以概括性地描述你负责的模块、使用的技术栈、解决的核心问题和取得的成效。
- 技术栈:可以具体介绍精通的编程语言(如Java、Python),掌握的框架或工具(如Spring Boot、Django),以及数据库和开发工具的经验(如MySQL、Git)。
- 项目细节:对于项目,可以选择一两个具有代表性的项目进行详细说明。建议结构如下:
- 项目背景及目标
- 你在项目中的角色及承担的主要工作
- 项目过程中遇到的挑战和你如何解决这些问题
- 项目的最终成果及其影响(数据和结果能帮助量化)
2. 操作系统
虚拟线程
虚拟线程(virtual thread)是现代编程语言(如Java)中为提高并发性能而引入的轻量级线程机制。相比传统线程,虚拟线程的创建和销毁代价更低,更适合高并发场景。
虚拟线程的内存置换
在操作系统中,线程切换时一般涉及线程上下文的保存和恢复,主要是寄存器的内容。虚拟线程并不直接影响内存置换的实现,内存置换是操作系统管理内存时根据页面使用情况进行的。
操作系统的内存置换机制
在操作系统中,内存置换的实现方式通常包括:
- 分页机制:操作系统将进程的内存分为多个大小固定的页面,当内存不足时,通过页面置换将部分页面交换到磁盘中。
- 页面置换算法:页面置换算法决定哪些页面需要被交换,例如FIFO、LRU(最近最少使用)、LFU(最少使用频率)、Clock算法等。
进程、线程、协程的区别
特性 | 进程 | 线程 | 协程 |
---|---|---|---|
定义 | 操作系统资源分配的基本单位 | 进程内的执行单位 | 用户空间的轻量级线程 |
调度方式 | 由操作系统调度 | 由操作系统调度 | 由程序自行控制(协作调度) |
内存独立性 | 进程间相互独立 | 线程共享同一进程的内存空间 | 运行在线程内共享线程的内存 |
切换开销 | 高 | 较低 | 极低 |
使用场景 | 适用于隔离性要求高的任务 | 并发执行IO密集型或CPU密集型任务 | 高并发IO操作、协同任务处理 |
3. 计算机网络
开放性问题:A机器发送报文到B机器途中有哪些可能原因会导致丢包?
可能导致报文丢失的原因如下:
- 网络拥塞:路由器、交换机等中间设备处理能力有限,当流量超过其处理能力时,可能会丢弃部分报文。
- 链路错误:在传输介质(如铜线、光纤)上可能会受到电磁干扰、噪声等影响导致数据错误而被丢弃。
- TTL(生存时间)超时:IP报文有一个TTL字段,每经过一个路由器减少1,若TTL为0报文会被丢弃。
- 防火墙过滤:网络路径中某些防火墙设置可能会根据报文内容或端口策略丢弃某些报文。
- ARP缓存未更新:A机器可能没有B机器的最新ARP记录,导致数据发送错误。
- 设备故障:路由器、交换机或网卡等设备故障也可能导致丢包。
4. 算法题:LCR 023. 相交链表
题目描述: 给定两个单链表,判断它们是否相交,如果相交,返回相交的起始节点。假设链表结构不可变,且不使用额外内存空间。
解题思路:
- 双指针法:使用两个指针分别从两个链表的头开始遍历。当某一指针遍历完一条链表后,从另一条链表头开始,最终在相交点相遇。
代码实现:
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
def getIntersectionNode(headA: ListNode, headB: ListNode) -> ListNode:
if not headA or not headB:
return None
pA, pB = headA, headB
# 两个指针走过相同长度(A链表+B链表),最终相遇或到达None
while pA != pB:
# 如果pA到达末尾则转到headB,否则继续向下
pA = pA.next if pA else headB
# 如果pB到达末尾则转到headA,否则继续向下
pB = pB.next if pB else headA
return pA # 返回相交节点或None(不相交)
复杂度分析:
- 时间复杂度:O(m + n),m和n是两个链表的长度。
- 空间复杂度:O(1),只用了两个指针,不需要额外空间。
解释: 通过双指针法,两个指针的总路程相同,如果链表相交,指针会在相交节点处相遇;如果不相交,最终两个指针都会走到链表尾部的None。