软件工程师面试题集及详解_第1页
软件工程师面试题集及详解_第2页
软件工程师面试题集及详解_第3页
软件工程师面试题集及详解_第4页
软件工程师面试题集及详解_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

2026年软件工程师面试题集及详解一、编程题(共5题,每题10分,总分50分)1.题目:编写一个函数,实现字符串的压缩。输入一个字符串,如果字符串中有连续的相同字符,则用字符和出现的次数表示。例如,输入"aaabbbcc",输出"a3b3c2"。如果压缩后的字符串不比原字符串短,则返回原字符串。答案:pythondefcompress_string(s):ifnots:returnscompressed=[]count=1foriinrange(1,len(s)):ifs[i]==s[i-1]:count+=1else:compressed.append(s[i-1]+str(count))count=1compressed.append(s[-1]+str(count))compressed_str=''.join(compressed)returncompressed_striflen(compressed_str)<len(s)elses解析:-首先检查输入字符串是否为空,若为空则直接返回。-使用一个列表`compressed`存储压缩后的字符和计数。-遍历字符串,统计连续相同字符的个数,当遇到不同字符时,将字符和计数添加到`compressed`中。-最后将最后一个字符及其计数添加到列表中,并拼接成字符串。-比较压缩后的字符串长度与原字符串长度,若压缩后更短则返回压缩字符串,否则返回原字符串。2.题目:实现一个二叉树的前序遍历(根-左-右)。不使用递归,使用栈实现。答案:pythonclassTreeNode:def__init__(self,val=0,left=None,right=None):self.val=valself.left=leftself.right=rightdefpreorder_traversal(root):ifnotroot:return[]stack,output=[root],[]whilestack:node=stack.pop()output.append(node.val)ifnode.right:stack.append(node.right)ifnode.left:stack.append(node.left)returnoutput解析:-定义二叉树节点类`TreeNode`。-使用栈`stack`和列表`output`实现前序遍历。-初始时将根节点入栈。-当栈不为空时,弹出栈顶节点,将其值添加到`output`中。-先将右子节点入栈(因为栈是后进先出,先处理右子节点),再将左子节点入栈。-最后返回`output`列表。3.题目:给定一个数组,找出其中不重复的三元组,使得这三个数的和为0。例如,输入[-1,0,1,2,-1,-4],输出[[-1,0,1],[-1,-1,2]]。答案:pythondefthree_sum(nums):nums.sort()result=[]foriinrange(len(nums)-2):ifi>0andnums[i]==nums[i-1]:continueleft,right=i+1,len(nums)-1whileleft<right:total=nums[i]+nums[left]+nums[right]iftotal==0:result.append([nums[i],nums[left],nums[right]])whileleft<rightandnums[left]==nums[left+1]:left+=1whileleft<rightandnums[right]==nums[right-1]:right-=1left+=1right-=1eliftotal<0:left+=1else:right-=1returnresult解析:-首先对数组进行排序,方便后续操作。-使用一个循环遍历数组,固定第一个数`nums[i]`。-对于每个`nums[i]`,使用双指针`left`和`right`分别指向`i+1`和数组末尾。-计算三个数的和`total`:-若`total==0`,则找到一个解,添加到结果中,并移动双指针跳过重复值。-若`total<0`,则左指针右移,增加和。-若`total>0`,则右指针左移,减少和。-最后返回所有解的列表。4.题目:实现一个LRU(最近最少使用)缓存。支持`get`和`put`操作。`get(key)`返回键对应的值,若不存在返回-1;`put(key,value)`插入或更新键值对,当缓存容量满时,删除最久未使用的键。答案:pythonclassLRUCache:def__init__(self,capacity:int):self.capacity=capacityself.cache={}self.order=[]defget(self,key:int)->int:ifkeyinself.cache:self.order.remove(key)self.order.append(key)returnself.cache[key]return-1defput(self,key:int,value:int)->None:ifkeyinself.cache:self.order.remove(key)eliflen(self.cache)==self.capacity:oldest_key=self.order.pop(0)delself.cache[oldest_key]self.cache[key]=valueself.order.append(key)解析:-使用字典`cache`存储键值对,列表`order`记录访问顺序。-`__init__`初始化缓存容量、字典和列表。-`get(key)`:-若键存在,则将其从`order`中移除并添加到末尾,表示最近使用。-返回对应的值,若不存在返回-1。-`put(key,value)`:-若键存在,则更新值,并调整`order`顺序。-若键不存在且缓存已满,则删除最久未使用的键(`order`的第一个元素)。-添加或更新键值对,并将键添加到`order`末尾。5.题目:实现快速排序算法,不使用递归,使用迭代(栈)实现。答案:pythondefquick_sort_iterative(arr):ifnotarr:returnarrstack=[(0,len(arr)-1)]whilestack:start,end=stack.pop()ifstart>=end:continuepivot=arr[end]i=start-1forjinrange(start,end):ifarr[j]<=pivot:i+=1arr[i],arr[j]=arr[j],arr[i]arr[i+1],arr[end]=arr[end],arr[i+1]pivot_index=i+1stack.append((start,pivot_index-1))stack.append((pivot_index+1,end))returnarr解析:-使用栈`stack`存储要处理的子数组范围。-初始时将整个数组范围入栈。-当栈不为空时,弹出栈顶范围,进行快速排序的分区操作:-选择最后一个元素作为基准`pivot`。-使用变量`i`记录小于基准的元素的最后位置。-遍历子数组,将小于基准的元素移到`i`的左边。-将基准元素放到正确的位置,并记录`pivot_index`。-将基准左右的子数组范围入栈,继续处理。-最后返回排序后的数组。二、系统设计题(共3题,每题15分,总分45分)1.题目:设计一个短链接服务,要求支持高并发、高可用、可扩展,并简要说明关键组件和算法。答案:关键组件:1.接入层(LoadBalancer):使用Nginx或HAProxy分发请求,支持多副本水平扩展。2.短链接生成服务(ShortenerService):负责生成短链接,使用分布式ID生成器(如Twitter的Snowflake算法)。3.存储服务(Redis/Memcached):缓存短链接与长链接的映射关系,支持高并发读写。4.数据库(MySQL/PostgreSQL):持久化存储短链接与长链接的映射,支持数据恢复和查询。5.CDN(ContentDeliveryNetwork):加速短链接页面的访问速度。6.监控与告警系统(Prometheus/Grafana):监控系统状态,及时发现并处理问题。算法:-短链接生成:使用Base62编码(包含a-z、A-Z、0-9),将长链接的ID映射为短链接。-例如,将长链接ID`123456`编码为`aBcD`。-长链接解析:使用Base62解码,将短链接还原为ID,再通过ID查询长链接。高并发与高可用:-接入层:使用负载均衡器分发请求,支持水平扩展。-短链接生成服务:使用分布式ID生成器,避免冲突。-存储服务:使用Redis/Memcached缓存热点数据,减少数据库压力。-数据库:使用读写分离、分库分表,提高性能和可用性。-冗余:关键组件部署多副本,使用Kubernetes进行容器化管理,确保高可用。解析:-短链接服务需要处理大量请求,因此高并发和高可用是关键。-接入层使用负载均衡器分发请求,支持水平扩展。-短链接生成服务使用分布式ID生成器,确保唯一性和高性能。-使用缓存和数据库分离,提高性能和可用性。-使用CDN加速访问速度,提高用户体验。-监控与告警系统及时发现并处理问题,确保系统稳定运行。2.题目:设计一个实时消息推送系统,要求支持高并发、低延迟、可扩展,并简要说明关键组件和协议。答案:关键组件:1.接入层(LoadBalancer):使用Nginx或HAProxy分发请求,支持多副本水平扩展。2.消息接入服务(MessageIngestionService):负责接收客户端消息,支持WebSocket或MQTT协议。3.消息存储服务(MessageStorageService):使用Redis或Kafka存储消息,支持高并发读写。4.消息分发服务(MessageDistributionService):负责将消息推送给目标客户端,支持广播和单播。5.用户管理服务(UserManagementService):管理用户信息,支持在线状态同步。6.监控与告警系统(Prometheus/Grafana):监控系统状态,及时发现并处理问题。协议:-WebSocket:支持全双工通信,低延迟。-MQTT:轻量级消息传输协议,适合移动端和低带宽环境。高并发与低延迟:-接入层:使用负载均衡器分发请求,支持水平扩展。-消息接入服务:支持WebSocket和MQTT协议,接收客户端消息。-消息存储服务:使用Redis或Kafka存储消息,支持高并发读写。-消息分发服务:支持广播和单播,使用发布订阅模式,提高效率。-用户管理服务:实时同步用户在线状态,确保消息推送给正确的客户端。-冗余:关键组件部署多副本,使用Kubernetes进行容器化管理,确保高可用。解析:-实时消息推送系统需要支持高并发和低延迟。-接入层使用负载均衡器分发请求,支持水平扩展。-消息接入服务支持WebSocket和MQTT协议,接收客户端消息。-消息存储服务使用Redis或Kafka,支持高并发读写。-消息分发服务支持广播和单播,使用发布订阅模式,提高效率。-用户管理服务实时同步用户在线状态,确保消息推送给正确的客户端。-监控与告警系统及时发现并处理问题,确保系统稳定运行。3.题目:设计一个分布式任务调度系统,要求支持任务分片、任务依赖、任务重试,并简要说明关键组件和算法。答案:关键组件:1.任务注册中心(TaskRegistry):注册和管理任务,支持任务分片和依赖。2.任务调度器(TaskScheduler):负责调度任务,支持任务分片和依赖。3.任务执行器(TaskExecutor):负责执行任务,支持任务重试和状态跟踪。4.任务状态存储(TaskStateStorage):使用Redis或数据库存储任务状态,支持高并发读写。5.监控与告警系统(Prometheus/Grafana):监控系统状态,及时发现并处理问题。算法:-任务分片:将大任务分解为多个小任务,分配给不同的执行器。-任务依赖:使用有向无环图(DAG)表示任务依赖关系,确保任务按顺序执行。-任务重试:使用指数退避算法,避免任务频繁失败。高并发与可扩展:-任务注册中心:使用分布式缓存,支持任务分片和依赖。-任务调度器:使用分布式队列,支持任务分片和依赖。-任务执行器:支持任务重试和状态跟踪,使用幂等性设计,避免重复执行。-任务状态存储:使用Redis或数据库,支持高并发读写。-冗余:关键组件部署多副本,使用Kubernetes进行容器化管理,确保高可用。解析:-分布式任务调度系统需要支持任务分片、任务依赖和任务重试。-任务注册中心注册和管理任务,支持任务分片和依赖。-任务调度器负责调度任务,支持任务分片和依赖。-任务执行器负责执行任务,支持任务重试和状态跟踪。-任务状态存储使用Redis或数据库,支持高并发读写。-监控与告警系统及时发现并处理问题,确保系统稳定运行。三、数据库题(共2题,每题10分,总分20分)1.题目:解释数据库事务的ACID特性,并举例说明。答案:ACID特性:1.原子性(Atomicity):事务中的所有操作要么全部成功,要么全部失败,不会停留在中间状态。-例子:银行转账,从A账户扣款100元,同时向B账户加款100元。如果其中一个操作失败,整个事务回滚。2.一致性(Consistency):事务必须保证数据库从一个一致性状态转移到另一个一致性状态。-例子:银行转账后,A账户金额减少100元,B账户金额增加100元,总金额不变。3.隔离性(Isolation):并发事务之间互不干扰,每个事务都感觉不到其他事务的存在。-例子:两个用户同时查询库存,每个查询都看到一致的库存数据。4.持久性(Durability):事务一旦提交,其结果就永久保存在数据库中,即使系统崩溃也不会丢失。-例子:银行转账成功后,A账户扣款100元,即使系统崩溃,数据也不会丢失。解析:-ACID特性是数据库事务的重要保证,确保数据的一致性和可靠性。-原子性保证事务的完整性,要么全部成功,要么全部失败。-一致性保证数据库状态的一致性,事务执行前后数据满足一致性约束。-隔离性保证并发事务的独立性,避免相互干扰。-持久性保证事务结果的永久性,即使系统崩溃也不会丢失。2.题目:解释数据库索引的作用,并举例说明不同类型的索引。答案:索引作用:1.提高查询性能:通过索引可以快速定位数据,减少查询时间。-例子:使用索引查询用户姓名为"张三"的用户,无需扫描整个表。2.加速排序和分组:索引可以加速排序和分组操作。-例子:使用索引按年龄排序用户,无需扫描整个表。3.保证唯一性:主键索引和唯一索引可以保证数据的唯一性。-例子:使用主键索引保证用户ID的唯一性。不同类型的索引:1.B-Tree索引:最常用的索引类型,适用于范围查询和精确查询。-例子:使用B-Tree索引查询年龄在20到30岁的用户。2.哈希索引:适用于精确查询,不支持范围查询。-例子:使用哈希索引查询用户ID为100的用户。3.全文索引:适用于文本搜索,支持模糊查询。-例子:使用全文索引查询包含"张三"的用户。4.空间索引:适用于地理空间数据,支持空间查询。-例子:使用空间索引查询某个区域内的用户。解析:-索引是数据库的重要数据结构,可以提高查询性能,加速排序和分组操作,保证数据的唯一性。-B-Tree索引是最常用的索引类型,适用于范围查询和精确查询。-哈希索引适用于精确查询,不支持范围查询。-全文索引适用于文本搜索,支持模糊查询。-空间索引适用于地理空间数据,支持空间查询。四、网络题(共2题,每题10分,总分20分)1.题目:解释TCP的三次握手过程,并说明每次握手的作用。答案:TCP三次握手过程:1.第一次握手(SYN):客户端向服务器发送SYN包,请求建立连接,SYN包中包含初始序列号`client_isn`。-作用:客户端请求建立连接。2.第二次握手(SYN+ACK):服务器收到SYN包后,回复SYN+ACK包,ACK号为`client_isn+1`,SYN号为`server_isn`。-作用:服务器同意建立连接。3.第三次握手(ACK):客户端收到SYN+ACK包后,回复ACK包,ACK号为`server_isn+1`。-作用:客户端确认连接建立。解析:-TCP三次握手确保客户端和服务器之间的连接建立可

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论