近几年字节测开部分面试题整理

news2025/4/25 21:42:40

文章目录

  • 前言
  • 一、面试问题
    • 1. 在浏览器url上写一个地址,请描述一下网络方面有哪些变化
    • 2. 堆栈数据存储位置
    • 3. HTTP POST请求支持的数据格式
    • 4. 缩容要注意些什么?
    • 5. Python中元组、数组、list和数组的区别
    • 6. Python中is和==的区别
    • 7. HTTP与HTTPS
    • 8. 已知两个ip地址,它们是怎么实现传输的?(网络层及以下)
    • 9. IO操作相关
    • 10. 网络拥塞
    • 11. HTTP常用状态码
    • 12. Websocket是长连接还是短连接?
    • 13. Session和token有啥区别?哪个安全?
    • 14. 分析一下视频卡住的原因
    • 15. 断点续传怎么实现?
    • 16. socket通信过程
  • 二、测试案例设计
    • 1. 如何测试抖音软件
    • 2. 将数据从一个库,一张表迁移到多个库多张表怎么测试
    • 3. 发送红包测试用例
    • 4. 微信朋友圈评论功能测试案例
  • 三、手撕算法
    • 1. 无重复字符的最长子串
    • 2. 用两个栈实现队列
    • 3. 找众数-Moore投票算法
    • 4. 买卖股票的最佳时机
    • 5. 求2的N次幂
    • 6. 兔子繁殖问题
    • 7. 删除链表的倒数第N个结点
    • 8. 存在重复元素III
    • 9. 最大数
    • 10. 给10人随机分配100元红包,每人最低获取1元
  • 总结


前言

面经收集于牛客网上,部分面试题时间可能有些久了,此处只是做个学习整理。大多数题目的回答来自于deepseek。


一、面试问题

1. 在浏览器url上写一个地址,请描述一下网络方面有哪些变化

  1. URL解析
    • 协议解析:浏览器检查URL的协议(如 https://),决定使用HTTPS(默认端口443)或HTTP(默认端口80)。
    • 域名提取:从URL中提取主机名
  2. DNS解析
    • 浏览器缓存:首先检查本地缓存是否有域名对应的IP地址。
    • 系统缓存:若浏览器无缓存,查询操作系统缓存。
    • 递归查询:向配置的本地DNS服务器(如ISP提供的服务器)发起请求。若本地DNS无记录,则从根DNS(.)开始迭代查询 → 顶级域(.com) → 权威DNS(example.com的NS记录),最终获取IP地址。
    • DNS结果缓存:将解析结果缓存到本地,加速后续访问。
  3. 建立TCP连接
    • 三次握手
      1. 客户端发送SYN包到服务器IP的443端口。
      2. 服务器回复SYN-ACK
      3. 客户端发送ACK,完成连接建立。
    • TLS(HTTPS)
      1. 客户端发送ClientHello,包含支持的加密算法。
      2. 服务器回复ServerHello,选择加密算法并发送证书。
      3. 客户端验证证书(如CA机构签名),生成会话密钥,用证书公钥加密后发送。
      4. 服务器用私钥解密,双方启用加密通信。
  4. 发送HTTP请求(请求行、请求头、请求体)
  5. 服务器处理请求(执行后端代码,生成响应)
  6. 接收HTTP响应(状态行、响应头、响应体)
  7. 浏览器渲染
  8. 连接终止
    • 四次挥手(TCP关闭):
      1. 客户端发送FIN
      2. 服务器回复ACK
      3. 服务器发送FIN
      4. 客户端回复ACK,连接关闭。

2. 堆栈数据存储位置

    1. 存储位置:位于内存的高地址区域,通常向低地址方向增长。
    2. 存储内容:函数调用时的局部变量、函数参数、返回地址、寄存器上下文。
    3. 管理方式:由编译器自动分配和释放,遵循LIFO(后进先出)原则。
    4. 特点:分配和释放速度快、内存大小有限、内存连续、大小在编译时通常就确定了
    1. 存储位置:位于内存的低地址区域,通常向高地址方向增长。
    2. 存储内容:动态分配的内存(malloc/new等)、全局变量、静态变量
    3. 管理方式:由程序员手动分配和释放(或由垃圾回收器管理)
    4. 特点:分配和释放速度相对较慢、内存大小受系统可用内存限制、内存可以不连续、大小在运行时动态确定

3. HTTP POST请求支持的数据格式

HTTP POST 请求可以支持多种数据格式,主要通过 Content-Type 请求头来指定。

  1. 表单数据(Form Data):application/x-www-form-urlencoded
  2. 多部分表单数据(Multipart Form Data):multipart/form-data
  3. JSON格式:application/json
  4. 纯文本:text/plain
  5. 二进制数据:application/octet-stream

4. 缩容要注意些什么?

缩容(减少系统资源)是云计算和系统运维中的重要操作,需要注意以下关键点:

  1. 业务影响评估
    • 确认缩容时段是否避开业务高峰期
    • 评估可能对用户体验造成的影响
  2. 容量规划
    • 确保剩余资源能满足当前业务需求
    • 保留适当的缓冲资源应对突发流量
  3. 数据安全
    • 缩容前做好数据备份
    • 确保无单点故障产生
  4. 监控与告警
    • 缩容后密切监控系统指标
    • 准备好快速回滚方案

实施步骤建议:

  1. 先在非生产环境测试缩容方案
  2. 采用渐进式缩容而非一次性大幅缩减
  3. 记录缩容前后的性能指标对比
  4. 通知相关团队缩容计划

5. Python中元组、数组、list和数组的区别

  1. 数组和list的区别

    特性数组(array.array)列表(List)
    数据类型同类型元素可混合类型
    性能数值操作更快更灵活但稍慢
    内存更节省内存占用更多内存
    内置支持需要import array内置支持
  2. 列表 (List) vs 元组 (Tuple) vs 集合 (Set) vs 字典 (Dict)

    特性列表(List)元组(Tuple)集合(Set)字典(Dict)
    可变性可变不可变可变可变
    有序性有序有序无序Python 3.7+ 有序
    重复元素允许允许不允许键不允许,值允许
    语法[1, 2, 3](1, 2, 3){1, 2, 3}{'a': 1, 'b': 2}
    查找效率O(n)O(n)O(1)键查找O(1)
    用途有序数据集合不可变数据集合去重、成员测试键值对映射
  3. 选择建议

    • 需要有序且可变的集合 → 列表
    • 需要不可变的有序集合 → 元组
    • 需要快速成员测试去重 → 集合
    • 需要键值对映射 → 字典
    • 需要两端高效操作 → deque
  4. 列表 (List) vs 元组 (Tuple)

    特性列表(List)元组(Tuple)
    可变性可变不可变
    语法[1, 2, 3](1, 2, 3)
    性能稍慢更快
    内存占用较多较少
    使用场景需要修改的数据集合固定不变的数据集合

6. Python中is和==的区别

特性==is
比较内容值是否相等是否是同一个对象
可重载性可重载(__eq__不可重载
执行速度相对较慢相对较快
适用场景常规值比较单例对象、对象身份验证

7. HTTP与HTTPS

  1. 区别

    HTTPHTTPS
    默认端口80默认端口443
    POST明文传输、数据未加密、安全性差传输过程ssl加密、安全性较好
    响应速度快、消耗资源少响应速度较慢、消耗资源多、需要用到CA证书
  2. HTTPS链接建立的过程

    1. 客户端发送ClientHello,包含支持的加密算法。
    2. 服务器回复ServerHello,选择加密算法并发送证书。
    3. 客户端验证证书(如CA机构签名),生成会话密钥,用证书公钥加密后发送。
    4. 服务器用私钥解密,双方启用加密通信。
  3. 对称加密和非对称加密

    • 对称加密
      1. 单一密钥:加密和解密使用同一个密钥
      2. 高效快速:加密速度快,适合大数据量加密
      3. 算法举例:AES、DES
    • 非对称加密:
      1. 密钥对:公钥(公开)和私钥(保密),相比对称加密速度较慢
      2. 数学关联:公钥私钥成对生成,有数学关系
      3. 算法举例:RSA、DSA

8. 已知两个ip地址,它们是怎么实现传输的?(网络层及以下)

当两个IP地址之间进行通信时,在不考虑传输层及以上协议(如TCP/UDP)的情况下,数据通过以下机制实现传输:

  1. 路由决策
    • 源主机查询路由表确定数据包下一跳
    • 判断目标IP是否在同一子网
  2. ARP解析
    • 同一子网:通过ARP获取目标MAC地址
    • 不同子网:获取默认网关MAC地址
  3. 帧封装
  4. 物理传输
    • 以太网:CSMA/CD(冲突检测)
    • 交换机:MAC地址表转发
    • 路由器:解封装->路由决策->重新封装

9. IO操作相关

  1. 什么是I/O操作?

    IO操作(Input/Output Operation,输入/输出操作)是指计算机系统与外部世界或其他设备之间进行的数据交换过程。

    主要类型

    • 输入操作(input):从外部设备(如键盘、鼠标、磁盘、网络等)读取数据到计算机内存中

      例如:读取文件、接收网络数据、获取用户键盘输入

    • 输出操作(output):将计算机内存中的数据写入到外部设备

      例如:写入文件、发送网络数据、在屏幕上显示内容

    常见IO形式:文件IO、网络IO、控制台IO、设备IO

    技术特点

    1. 速度差异:IO操作通常比CPU和内存操作慢得多
    2. 阻塞与非阻塞:
      • 阻塞IO:操作完成前程序会暂停
      • 非阻塞IO:操作立即返回,不等待完成
    3. 同步与异步:
      • 同步IO:程序等待操作完成
      • 异步IO:操作在后台进行,完成后通知程序
  2. 什么情况会使得IO变慢?为什么?

    1. 硬件限制
      • 存储介质速度
        • HDD机械硬盘(约80-160MB/s)比SSD(约200-550MB/s)慢得多
        • 网络存储(NAS/SAN)通常比本地存储慢
      • 接口带宽
        • USB 2.0(480Mbps)比USB 3.0(5Gbps)慢
        • SATA III(6Gbps)比NVMe(PCIe 3.0 x4可达4GB/s)慢
      • 设备老化:存储设备随着使用时间增长性能下降
    2. 系统资源竞争
      • CPU负载过高:无法及时处理I/O请求
      • 内存不足:导致频繁的交换(Swap)操作
      • 并发I/O过多:多个进程/线程同时访问同一设备
      • 缓存未命中:需要直接从较慢的存储介质读取
    3. 软件因素
      • 小文件频繁读写:大量小文件操作比单个大文件慢
      • 随机访问:HDD上随机读写比顺序读写慢100倍以上
      • 缓冲区大小不当:过小的缓冲区增加I/O次数
      • 同步写入策略:确保数据落盘的操作(如fsync)显著变慢
      • 文件系统碎片:特别是FAT32/NTFS等传统文件系统
    4. 网络IO特定问题
      • 高延迟网络:跨国或卫星网络连接
      • 带宽限制:网络带宽被其他应用占用
      • 协议开销:如TCP握手、加密/解密过程
      • 数据包丢失:导致重传和等待
    5. 其他因素
      • 虚拟化开销:在虚拟环境中I/O需要额外转换
      • 安全扫描:实时病毒扫描等安全检查
      • 日志记录:详细的I/O操作日志会增加开销
      • 温度过高:可能导致设备自动降速
  3. 什么是虚拟内存?

    虚拟内存是计算机系统内存管理的一种技术,它通过将**物理内存(RAM)磁盘存储(如硬盘或SSD)**结合起来,为程序提供一个比实际物理内存更大的地址空间。这使得每个程序可以认为自己拥有连续且独立的内存空间,而不必关心其他程序的内存使用情况。

  4. IO频繁对虚拟内存有什么影响?为什么?主要影响

    1. 加速交换活动:内存压力过大、换页增加、双重I/O负担
    2. 性能下降:系统花费更多时间在数据交换而非实际计算
    3. TLB(转换检测缓冲区)效率下降:频繁的页交换导致地址转换缓存失效
    4. 文件系统缓存受影响:频繁I/O占用缓存空间,挤出了可能更有用的数据

    原因分析:

    1. 磁盘带宽竞争
      • 数据流冲突:应用I/O和交换I/O共享同一磁盘通道
      • 寻道时间增加:磁头需要在数据区和交换区间频繁移动(HDD尤其明显)
    2. 内存压力机制
      • 脏页回写:文件I/O产生的脏页需要定期写回磁盘
      • 回收算法负担:页面替换算法(如LRU)需要更频繁工作
    3. 上下文切换开销
      • 进程调度:I/O等待导致更多上下文切换
      • 缺页中断:触发更多缺页异常处理
    4. 写放大效应
      • 元数据更新:每次I/O可能伴随inode、目录等元数据更新
      • 日志开销:日志型文件系统需要额外写入日志记录

10. 网络拥塞

  1. 什么是网络拥堵

    网络拥堵是指网络中的数据流量超过其承载能力,导致传输延迟增加、丢包率上升、吞吐量下降的现象。类似于交通堵塞,当太多设备同时发送数据时,网络设备(如路由器、交换机)无法及时处理,就会发生拥堵。

  2. 怎么解决?

    1. 增加带宽(扩容)
    2. 流量控制
      • 优先级调度:保障关键业务(如视频会议)优先传输
      • 限速(Rate Limiting):限制P2P下载、视频流媒体占用过多带宽
      • 队列管理:采用先进队列算法(如FQ-CoDel)减少缓冲延迟
    3. 优化TCP/IP协议
      • 使用BBR拥塞控制算法(Google开发,比传统CUBIC更高效)
      • 调整TCP窗口大小,减少重传
    4. 负载均衡
      • 使用多WAN口路由器,分流不同运营商的流量
      • CDN(内容分发网络)就近提供数据,减少主干网压力
    5. 减少不必要的流量
      • 启用数据压缩(如HTTP/2、Brotli)
      • 缓存静态资源(如浏览器缓存、CDN缓存)
      • 限制后台自动更新(如Windows Update、云同步)
  3. 什么情况会造成拥堵?

    • 带宽不足
    • 网络设备瓶颈
    • 突发流量
    • TCP/IP协议特性
    • 网络拓扑设计不合理
  4. 什么是拥塞控制

    拥塞控制是计算机网络中的一种关键机制,用于防止网络因数据流量过大而超载,确保网络高效、公平地运行。它主要应用于传输层协议(如TCP),但现代网络设备(如路由器)也会参与拥塞管理。

    拥塞控制的目标是让发送方动态调整数据发送速率,使网络流量接近但不超出其承载能力(即“拥塞避免”)。

    TCP拥塞控制的4个核心算法:

    • 慢启动:发送方从极小的窗口(如1MSS)开始,指数级增长发送速率。

      目的:快速探测可用带宽,避免一开始就冲击网络。

    • 拥塞避免:当窗口达到阈值(ssthresh)后,改为每RTT(往返时间)增加1个MSS

      目的:接近网络容量时谨慎提速,避免引发拥塞。

    • 快速重传:如果收到3个重复ACK,立即重传丢失的包(而不必等超时)

      目的:减少因等待超时带来的延迟。

    • 快速恢复:丢包后,窗口减半(而非重置为1),然后继续线性增长。

      避免因单次丢包导致吞吐量骤降。

11. HTTP常用状态码

状态码解释
100Continue — 继续。客户端应继续其请求。
200OK — 请求成功。一般用于GET与POST请求。
301Moved Permanently — 永久重定向。
302Found — 暂时重定向。
400Bad Request — 客户端请求的语法错误,服务器无法理解。
403Forbideen — 服务器理解请求客户端的请求,但是拒绝执行此请求。
404Not Found — 服务器无法根据客户端的请求找到资源(网页)。
500Internal Server Error — 服务器内部错误,无法完成请求。
502Bad Gateway — 作为网关或者代理服务器尝试执行请求时,从远程服务器接收到了无效的响应。

12. Websocket是长连接还是短连接?

websocket是长连接

关键区别:

短连接(如HTTP):

  • 每次请求都需要建立新的 TCP 连接,请求完成后立即断开。
  • 频繁的连接/断开开销大,不适合实时通信。

长连接(如websocket):

  • 客户端和服务器通过一次 HTTP 握手升级为 WebSocket 协议后,保持 TCP 连接持久化
  • 连接建立后,双方可以随时双向通信(服务器可主动推送,客户端可随时发送消息)。
  • 适合实时应用(聊天、游戏、股票行情等)。

WebSocket 的特点

  • 一次握手,长期复用:通过 HTTP 协议升级建立连接后,后续通信无需重复握手。
  • 低延迟:避免了 HTTP 的多次连接开销。
  • 双向通信:不同于 HTTP 的“请求-响应”模式,WebSocket 允许服务器主动推送数据。

13. Session和token有啥区别?哪个安全?

关键区别对比:

特性SessionToken(如JWT)
存储位置服务端存储会话数据客户端存储Token(无状态)
通信方式依赖Cookie通常通过Authorization
安全性风险CSRF(需额外防护)Token 泄露(需 HTTPS+短期过期)
扩展性服务器集群需共享Session天然支持分布式
主动失效服务端可立即注销需额外实现黑名单或短期过期

Session更安全(如果安全防护)

  • 服务端可控性强,能主动终止会话。
  • session_id 本身无意义,泄露后需进一步攻击(如窃取 Cookie)。

14. 分析一下视频卡住的原因

  1. 网络问题
    1. 带宽不足
    2. 网络抖动或丢包
    3. DNS或CDN问题
  2. 设备性能问题
    1. 硬件解码能力不足
    2. 内存或存储不足
  3. 视频编解码问题
    1. 编码格式不兼容
    2. 码率或帧率过高
  4. 服务端或播放器问题
    1. 服务端负载过高
    2. 播放器Bug或缓存策略
  5. 其他原因
    1. 协议或传输问题
    2. 防火墙/代理限制

解决方案

  1. 网络问题:升级带宽、切换WiFi/有线、优化CDN。
  2. 设备问题:更换设备、启用硬解、清理内存。
  3. 编码问题:服务端提供多码率流(如HLS自适应)。
  4. 播放器问题:更新版本、调整缓冲策略(如ExoPlayer的minBufferMs)。

通过分层排查(网络→设备→编码→服务端),可快速定位问题根源。

15. 断点续传怎么实现?

断点续传(Resumable Upload/Download)允许文件传输中断后,从中断的位置继续传输,而不是重新开始。其核心实现依赖于分块传输、记录进度、校验一致性。以下是具体实现方案:

核心机制

  1. 文件分块(Chunking)
    • 将大文件分割成固定大小的小块(如每块1MB),逐个传输。
    • 优势:避免单次传输失败导致全盘重试。
  2. 进度记录
    • 客户端:记录已成功传输的块序号或字节位置(持久化到本地文件或数据库)。
    • 服务端:保存已接收的块信息(如通过Range头或自定义元数据)。
  3. 唯一标识文件
    • 使用文件哈希(如MD5/SHA1)或唯一ID标识文件,确保续传时文件未修改。
  4. 校验完整性
    • 传输完成后校验整体文件哈希,确保分块合并后无错误

16. socket通信过程

  1. 服务器端(Server)
    1. Server->>Server: 1. 创建Socket (socket())
    2. Server->>Server: 2. 绑定IP和端口 (bind())
    3. Server->>Server: 3. 监听连接 (listen())
    4. Server->>Server: 4. 接受客户端连接 (accept())
    5. Server->>Client: 5. 读写数据 (read()/write())
    6. Server->>Server: 6. 关闭Socket (close())
  2. 客户端(Client)
    1. Client->>Client: 1. 创建Socket (socket())
    2. Client->>Server: 2. 连接服务器 (connect())
    3. Client->>Server: 3. 读写数据 (read()/write())
    4. Client->>Client: 4. 关闭Socket (close())

二、测试案例设计

1. 如何测试抖音软件

抖音作为一款短视频社交软件,测试需要覆盖功能、性能、兼容性、安全性和用户体验等多个方面。

  1. 功能测试
    1. 核心功能测试
      • 视频播放测试
        • 正常网络下视频自动播放
        • 滑动切换视频的流畅性
        • 暂停/继续播放功能
        • 全屏/退出全屏模式
        • 不同格式视频兼容性(MP4, MOV等)
      • 用户交互测试
        • 点赞、评论、收藏功能
        • 分享功能(微信、QQ、微博等平台)
        • 关注/取消关注用户
        • @功能测试
        • 私信功能
    2. 拍摄与编辑功能
      • 摄像头切换(前后置)
      • 滤镜效果测试
      • 音乐添加与同步
      • 特效功能(慢动作、快进等)
      • 视频剪辑功能
      • 草稿保存与编辑
  2. 性能测试
    • 启动时间测试(冷启动、热启动)
    • 视频加载时间(不同网络环境下)
    • 内存占用测试
    • CPU使用率测试
    • 长时间使用后的性能表现
    • 多任务切换测试
  3. 兼容性测试
    • 设备兼容性
      • 不同品牌手机(华为、小米、OPPO等)
      • 不同屏幕分辨率
      • 不同Android/iOS版本
    • 网络兼容性
      • 4G/5G/WiFi切换
      • 弱网环境测试
      • 网络中断恢复
  4. 安全性测试
    • 用户隐私保护
    • 数据传输加密
    • 敏感词过滤
    • 举报功能有效性
    • 未成年保护模式
  5. 用户体验测试
    • 界面布局合理性
    • 操作流畅度
    • 新手引导有效性
    • 错误提示友好性
    • 无障碍功能测试

2. 将数据从一个库,一张表迁移到多个库多张表怎么测试

  1. 测试准备阶段
    1. 环境搭建
      • 源环境:搭建与生产一致的源数据库环境
      • 目标环境:准备多个目标数据库实例
      • 中间件:如需使用分库分表中间件(如ShardingSphere、MyCat等),需一并部署
    2. 测试数据准备
      • 全量数据:准备与生产数据量级相当的测试数据
      • 包含各种边界条件的数据(如空值、极值、特殊字符等)
      • 增量数据:模拟生产环境持续写入的场景
  2. 功能测试
    1. 数据完整性测试
      • 源库数据总量验证
      • 目标库数据总量验证
    2. 数据一致性测试
      • 字段映射验证:检查每个字段是否正确迁移
      • 数据类型校验:确保数据类型转换正确
      • 分片规则验证:确保数据按预期规则分布到不同库表
    3. 特殊场景测试
      • 主键冲突:测试重复主键的处理机制
      • 空值处理:验证空值和NULL值的迁移情况
      • 事务一致性:测试迁移过程中事务是否保持完整
  3. 性能测试
    1. 基准测试
      • 全量迁移性能:测量完整迁移所需时间
      • 增量同步性能:测试数据持续同步的延迟
    2. 压力测试
      • 高并发写入:模拟生产环境写入压力
      • 长时间运行:验证系统稳定性
    3. 资源监控
      • CPU、内存、IO、网络等资源使用情况监控
      • 数据库连接数监控
  4. 异常测试
    1. 故障恢复测试
      • 网络中断:模拟迁移过程中网络故障
      • 数据库宕机:测试源库或目标库宕机场景
      • 中间件故障:如使用中间件,测试其故障恢复能力
    2. 回滚测试
      • 验证迁移失败后的回滚机制
      • 检查回滚后数据的一致性
  5. 验证工具
    1. 数据比对工具(比如:数据比对脚本)
    2. 自动化测试框架
      • 使用Jenkins等CI工具构建自动化测试流水线
      • 编写自动化测试用例覆盖各种场景
  6. 上线前验证
    1. 影子测试:在不影响生产环境的情况下全量运行迁移程序
    2. 数据校验:对迁移结果进行全面校验
    3. 性能基准:记录各项性能指标作为生产参考
  7. 监控方案
    1. 迁移进度监控:实时显示迁移进度
    2. 数据一致性监控:定期校验源库和目标库数据
    3. 报警机制:设置异常情况自动报警

3. 发送红包测试用例

  1. 功能测试
    1. 红包金额测试
      • 正常金额测试:发送0.01元、1元、100元、200元(假设200元为上限)
      • 边界值测试:发送0元、0.009元(四舍五入应为0.01元)、200.01元
      • 特殊金额测试:发送含小数的金额如8.88元、66.66元
      • 超大金额测试:尝试发送超过上限的金额如1000元
    2. 红包个数测试
      • 单个红包:发送给1个人
      • 多个红包:发送给2-100人(假设100人为上限)
      • 边界值测试:发送给0人、101人
      • 特殊个数测试:发送幸运数字如6、8、9个
    3. 红包类型测试
      • 普通红包:每个接收者金额相同
      • 拼手气红包:金额随机分配
      • 专属红包:指定给特定用户
    4. 支付方式测试
      • 余额支付:账户余额充足/不足
      • 银行卡支付:单卡/多卡支付
      • 组合支付:余额+银行卡组合
  2. 界面测试
    • 红包金额输入框:只能输入数字和小数点
    • 红包金额选择器:限制在合理范围内
    • 红包主题/祝福语:长度限制、表情支持
    • 发送按钮:金额不足时的提示
  3. 性能测试
    • 高并发发送红包测试
    • 大量用户同时抢红包测试
    • 红包发送响应时间测试
  4. 安全测试
    • XSS攻击测试:在祝福语中插入脚本
    • SQL注入测试:在输入字段尝试SQL注入
    • 金额篡改测试:拦截请求修改金额
    • 重复发送测试:防止重复扣款
  5. 兼容性测试
    • 不同操作系统:IOS、Android、鸿蒙
    • 不同微信版本测试
    • 不同屏幕尺寸适配
  6. 异常场景测试
    • 发送过程中网络中断
    • 支付密码错误
    • 账户冻结状态下发送红包
    • 红包过期未领取处理
  7. 数据校验测试
    • 发送后账户余额正确扣除
    • 接收方实际到账金额正确
    • 红包记录在交易明细中正确显示

4. 微信朋友圈评论功能测试案例

  1. 功能测试
    1. 基础评论功能
      • 发布一条朋友圈后,验证好友能否正常评论
      • 验证评论字数限制(如最多140个字符)
      • 验证评论中可包含的表情、图片、链接等特殊内容
      • 验证评论后能否正常显示评论者的昵称和头像
      • 验证评论时间的显示格式是否正确
    2. 评论交互功能
      • 验证评论后原作者能否收到通知
      • 验证评论后其他共同好友能否看到该评论
      • 验证评论后的回复功能是否正常
      • 验证评论后的点赞功能是否正常
      • 验证评论后的删除功能是否正常
  2. 权限测试
    1. 可见性权限
      • 验证不同好友分组对朋友圈的评论权限(如部分可见、不给谁看)
      • 验证陌生人(非好友)能否看到和参与评论
      • 验证被拉黑用户能否看到和参与评论
      • 验证朋友圈设置为"私密"时的评论权限
    2. 操作权限
      • 验证非好友能否删除他人评论
      • 验证朋友圈作者删除评论后,其他用户是否同步更新
      • 验证朋友圈作者能否禁止某人对某条朋友圈评论
  3. 性能测试
    1. 负载测试
      • 验证单条朋友圈下大量评论(如1000+)时的加载性能
      • 验证短时间内高频评论时的系统响应
    2. 稳定性测试
      • 验证长时间运行后评论功能的稳定性
      • 验证网络不稳定时评论功能的容错性
  4. 兼容性测试
    1. 设备兼容性
      • 验证不同机型(iOS/Android)评论功能的兼容性
      • 验证不同屏幕尺寸下的评论显示效果
    2. 版本兼容性
      • 验证新老版本微信客户端间的评论功能兼容性
      • 验证跨系统版本(如iOS 12与iOS 15)间的评论功能兼容性
  5. 安全测试
    1. 内容安全
      • 验证评论内容是否支持敏感词过滤
      • 验证评论中是否禁止包含恶意链接或代码
    2. 数据安全
      • 验证评论内容在传输过程中是否加密
      • 验证删除评论后服务器数据是否同步清除
  6. 异常测试
    1. 输入异常
      • 验证输入超长评论时的处理机制
      • 验证输入特殊字符(如emoji、HTML标签)时的处理
    2. 操作异常
      • 验证断网状态下发表评论的提示信息
      • 验证快速连续多次点击评论按钮的处理
  7. 用户体验测试
    1. 交互体验
      • 验证评论输入框的弹出和收起是否流畅
      • 验证评论后的消息提示是否及时准确
    2. 视觉体验
      • 验证评论列表的排版和显示效果
      • 验证夜间模式下的评论显示效果
  8. 国际化测试
    1. 多语言支持
      • 验证不同语言环境下的评论功能
      • 验证多语言混排评论的显示效果
    2. 时区支持
      • 验证不同时区下评论时间的显示准确性

这类题目太多了,这边就只列举了四个。。。

三、手撕算法

1. 无重复字符的最长子串

// leetcode原题:给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。
class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character, Integer> dic = new HashMap<>();
        char[] ch = s.toCharArray();
        int len = ch.length;
        int i = -1, res = 0;
        for(int j = 0; j < len; j++) {
            if(dic.containsKey(ch[j])) {
                i = Math.max(i, dic.get(ch[j]));
            }
            dic.put(ch[j], j);
            res = Math.max(res, j - i);
        }
        return res;
    }
}

2. 用两个栈实现队列

class MyQueue {

    private Deque<Integer> queueA;
    private Deque<Integer> queueB;

    public MyQueue() {
        queueA = new ArrayDeque<>();
        queueB = new ArrayDeque<>();
    }

    public void push(int x) {
        queueA.push(x);
    }

    public int pop() {
        if (queueB.isEmpty()) {
            while (!queueA.isEmpty()) {
                queueB.push(queueA.pop());
            }
        }
        return queueB.pop();
    }

    public int peek() {
        if (queueB.isEmpty()) {
            while (!queueA.isEmpty()) {
                queueB.push(queueA.pop());
            }
        }
        return queueB.peek();
    }

    public boolean empty() {
        return queueA.isEmpty() && queueB.isEmpty();
    }
}

3. 找众数-Moore投票算法

public class MajorityElement {

    // 这种方法不需要使用额外的空间,只需要遍历数组两次。
    // 第一次遍历找出候选众数,第二次遍历验证这个候选众数是否真的是众数。
    public static int findMajorityElement(int[] nums) {
        int count = 0;
        Integer candidate = null;

        for (int num : nums) {
            if (count == 0) {
                candidate = num;
            }
            count += (num == candidate) ? 1 : -1;
        }

        // 需要验证候选众数是否真的是众数(可选步骤,如果数组长度足够大,通常可以省省略)
        count = 0;
        for (int num : nums) {
            if (num == candidate) {
                count++;
            }
        }

        if (count > nums.length / 2) {   // 检查是否真的是众数
            return candidate;
        } else {
            throw new IllegalArgumentException("No mahority element found");
        }
    }

}

4. 买卖股票的最佳时机

// 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票
class Solution {
    public int maxProfit(int[] prices) {
        int maxProfit = 0;
        int min = prices[0];
        for (int i = 0; i < prices.length; i++) {
            min = Math.min(min, prices[i]);
            maxProfit = Math.max(maxProfit, prices[i] - min);
        }
        return maxProfit;
    }
}
// 在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
class Solution {
    public int maxProfit(int[] prices) {
        int profit = 0;
        for (int i = 1; i < prices.length; i++) {
            int tmp = prices[i] - prices[i - 1];
            if (tmp > 0) {
                profit += tmp;
            }
        }
        return profit;
    }
}
// 你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。
class Solution {
    public int maxProfit(int[] prices, int fee) {
        int n = prices.length;
        int[][] dp = new int[n][2];
        dp[0][0] = 0; // 手上没有股票
        dp[0][1] = -prices[0]; // 手上有股票
        for (int i = 1; i < n; i++) {
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i] - fee);
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
        }
        return dp[n - 1][0]; // 只有最后手里没有股票的时候,利润才有可能最大
    }
}
// 优化
class Solution {
    public int maxProfit(int[] prices, int fee) {
        int n = prices.length;
        int sell = 0; // 手上没有股票
        int buy = -prices[0]; // 手上有股票
        for (int i = 1; i < n; i++) {
            sell = Math.max(sell, buy + prices[i] - fee);
            buy = Math.max(buy, sell - prices[i]);
        }
        return sell; // 只有最后手里没有股票的时候,利润才有可能最大
    }
}

5. 求2的N次幂

public class PowerOfNumberIterative {

    public static void main(String[] args) {
        double result = power(2, 10);
        System.out.println(result);
    }

    // 迭代方法
    public static double power(double x, int n) {
        double result = 1.0;
        long longN = Math.abs((long) n);
        while (longN > 0) {
            if ((longN & 1) != 0) {  // 检查最低位是否为1(奇数情况)
                result *= x;    // 累乘底数x到结果中
            }
            x *= x; // 将底数平方以备下一次迭代使用(偶数情况)
            longN >>= 1; // 将指数右移一位(等同于除以2)
        }
        return n < 0 ? 1 / result : result; // 处理负指数的情况并返回最终结果
    }

    // 递归方法
    public static double power2(double x, int n) {
        if (n == 0) {
            return 1;
        }
        if (n < 0) {
            return 1 / power2(x, -n);
        }
        // 递归
        double half = power2(x, n / 2);
        if (n % 2 == 0) {
            return half * half;
        } else {
            return half * half * x;
        }
    }

}

6. 兔子繁殖问题

// 假设一对刚出生的兔子,从第三个月开始每个月都能生一对新兔子,新出生的兔子也是从第三个月开始繁殖。假设兔子不会死亡,问第n个月时有多少对兔子?
// 这个问题实际上就是著名的斐波那契数列(Fibonacci sequence):
// 第1个月:1对兔子(刚出生)
// 第2个月:1对兔子(还没成熟)
// 第3个月:2对兔子(原来的1对+新生的1对)
// 第4个月:3对兔子(原来的1对+上个月新生的1对又生1对)
// 第5个月:5对兔子
// ...
// 递推关系:f(n) = f(n-1) + f(n-2)
// 递归解法
public class RabbitRecursion {

    /**
     * 递归解决
     * 时间复杂度:O(2^n) - 指数级
     * 空间复杂度:O(n) - 调用栈深度
     */
    public static int fibonacciRecursive(int n) {
        if (n == 1 || n == 2) {
            return 1;
        }
        return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2);
    }

}

public class RabbitDP {

    /**
     * 动态规划解法(使用数组)
     * 时间复杂度(O(n))
     * 空间复杂度(O(n))
     */
    public static int fibonacciDP(int n) {
        if (n == 1 || n == 2) {
            return 1;
        }
        int[] dp = new int[n + 1];
        dp[1] = 1;
        dp[2] = 1;
        for (int i = 3; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }

    /**
     * 空间优化的动态规划解法
     * 时间复杂度:O(n)
     * 空间复杂度:O(1)
     */
    public static int fibonacciDPOptimized(int n) {
        if (n == 1 || n == 2) {
            return 1;
        }
        int prev = 1;
        int curr = 1;
        for (int i = 3; i <= n; i++) {
            int sum = prev + curr;
            prev = curr;
            curr = sum;
        }
        return curr;
    }

}

7. 删除链表的倒数第N个结点

// leetcode原题:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0, head);
        ListNode first = head;
        ListNode second = dummy;
        for (int i = 0; i < n; i++) {
            first = first.next;
        }
        while (first != null) {
            second = second.next;
            first = first.next;
        }
        second.next = second.next.next;
        ListNode res = dummy.next;
        return res;
    }
}

8. 存在重复元素III

// 给你一个整数数组 nums 和两个整数 indexDiff 和 valueDiff 。
// 找出满足下述条件的下标对 (i, j):
// i != j,
// abs(i - j) <= indexDiff
// abs(nums[i] - nums[j]) <= valueDiff
// 如果存在,返回 true ;否则,返回 false。
class Solution {
    public boolean containsNearbyAlmostDuplicate(int[] nums, int indexDiff, int valueDiff) {
        TreeSet<Long> set = new TreeSet<>();
        for (int i = 0; i < nums.length; i++) {
            Long num = (long) nums[i];
            // 找到比nums[i]小的最大元素
            Long floor = set.floor(num);
            if (floor != null && num - floor <= valueDiff) {
                return true;
            }
            // 找到比nums[i]大的最小元素
            Long ceiling = set.ceiling(num);
            if (ceiling != null && ceiling - num <= valueDiff) {
                return true;
            }
            set.add(num);
            // 维护滑动窗口大小不超过indexDiff
            if (i >= indexDiff) {
                set.remove((long) nums[i - indexDiff]);
            }
        }
        return false;
    }
}

9. 最大数

// 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。
class Solution {
    public String largestNumber(int[] nums) {
        // 1. 将 int 数组转换为 String 数组
        String[] numsStr = new String[nums.length];
        for (int i = 0; i < nums.length; i++) {
            numsStr[i] = String.valueOf(nums[i]);
        }
        // 2. 自定义排序规则:比较 ab 和 ba 的大小
        Comparator<String> comparator = new Comparator<String>() {
            @Override
            public int compare(String a, String b) {
                String ab = a + b;
                String ba = b + a;
                return ba.compareTo(ab); // 降序排列(ba > ab时,b排在前面)
            }
        };

        // 3. 排序
        Arrays.sort(numsStr, comparator);

        // 4. 处理前导零,应该返回0
        if (numsStr[0].equals("0")) {
            return "0";
        }

        // 5. 拼接结果
        StringBuilder sb = new StringBuilder();
        for (String num : numsStr) {
            sb.append(num);
        }
        return sb.toString();
    }
}
// 时间复杂度:O(n log n)(排序主导,n 是数组长度)。
// 空间复杂度:O(n)(存储字符串数组)。

10. 给10人随机分配100元红包,每人最低获取1元

public class RedPacket {

    public static int[] allocate(int totalAmount, int numPeople, int minAmount) {
        if (totalAmount < numPeople * minAmount) {
            throw new IllegalArgumentException("总金额不足以满足每人最低金额");
        }
        int remaining = totalAmount - numPeople * minAmount;
        int[] dividers = new int[numPeople - 1];
        Random random = new Random();

        // 生成numPeople - 1个随机隔板
        for (int i = 0; i < dividers.length; i++) {
            dividers[i] = random.nextInt(remaining + 1);
        }

        Arrays.sort(dividers);

        // 计算每个人的分配金额
        int[] result = new int[numPeople];
        int prev = 0;
        for (int i = 0; i < dividers.length; i++) {
            result[i] = dividers[i] - prev + minAmount;
            prev = dividers[i];
        }
        result[numPeople - 1] = remaining - prev + minAmount;
        return result;
    }

    public static void main(String[] args) {
        int[] amounts = allocate(100, 10, 1);
        System.out.println("分配结果:" + Arrays.toString(amounts));
        System.out.println("总和:" + Arrays.stream(amounts).sum()); // 验证总和
    }

}

总结

面试算法leetcode是王道,多练习总归会是有用的吧。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2342717.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

艾蒙顿桌面app下载-Emotn UI下载安装-emotn ui官方tv版安卓固件

在智能电视桌面应用的领域里&#xff0c;Emotn UI 凭借其简洁无广告、可自定义等特点&#xff0c;赢得了不少用户的关注。然而&#xff0c;小编深入了解后发现了一款更好用的电视桌面——乐看家桌面在诸多方面更具优势&#xff0c;能为你带来更优质的大屏体验。 乐看家桌面内置…

3、ArkTS语言介绍

目录 基础知识函数函数声明可选参数Rest参数返回类型箭头函数&#xff08;又名Lambda函数&#xff09;闭包 类字段字段初始化getter和setter继承父类访问方法重写方法重载签名可见性修饰符&#xff08;Public、Private、protected&#xff09; 基础知识 ArkTS是一种为构建高性…

修改了Element UI中组件的样式,打包后样式丢失

修改了Element UI中组件的样式&#xff0c;在本地运行没有问题&#xff0c;但是打包到线上发现样式丢失&#xff08;样式全部不生效、或者有一部分生效&#xff0c;一部分不生效&#xff09;&#xff0c;问题在于css的加载顺序导致代码编译后样式被覆盖了&#xff0c; 解决办法…

【springsecurity oauth2授权中心】jwt令牌更换成自省令牌 OpaqueToken P4

前言 前面实现了授权中心授权&#xff0c;客户端拿到access_token后就能请求资源服务器接口 权限的校验都是在资源服务器上进行的&#xff0c;授权服务器颁发的access_token有限期是2小时&#xff0c;也就是说在2小时之内&#xff0c;不管授权服务器那边用户的权限如何变更都…

诱骗协议芯片支持PD2.0/3.0/3.1/PPS协议,支持使用一个Type-C与电脑传输数据和快充取电功能

快充是由充电器端的充电协议和设备端的取电协议进行握手通讯进行协议识别来完成的&#xff0c;当充电器端的充电协议和设备端的取电协议握手成功后&#xff0c;设备会向充电器发送电压请求&#xff0c;充电器会根据设备的需求发送合适的电压给设备快速供电。 设备如何选择快充…

变量在template里不好使,在setup好使?

问题&#xff1a; 自定义的一个函数 &#xff0c;import导入后 setup里面使用正常 &#xff0c;在template里面说未定义 作用域问题 在 Vue 的模板语法中&#xff0c;模板&#xff08;template &#xff09;里能直接访问的是组件实例上暴露的属性和方法。从代码看&#xff0c…

OpenCV 图形API(53)颜色空间转换-----将 RGB 图像转换为灰度图像函数RGB2Gray()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 将图像从 RGB 色彩空间转换为灰度。 R、G 和 B 通道值的常规范围是 0 到 255。生成的灰度值计算方式如下&#xff1a; dst ( I ) 0.299 ∗ src…

Trae+DeepSeek学习Python开发MVC框架程序笔记(四):使用sqlite存储查询并验证用户名和密码

继续通过Trae向DeepSeek发问并修改程序&#xff0c;实现程序运行时生成数据库&#xff0c;用户在系统登录页面输入用户名和密码后&#xff0c;控制器通过模型查询用户数据库表来验证用户名和密码&#xff0c;验证通过后显示登录成功页面&#xff0c;验证失败则显示登录失败页面…

超详细mac上用nvm安装node环境,配置npm

一、安装NVM 打开终端&#xff0c;运行以下命令来安装NVM&#xff1a; curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash 然后就会出现如下代码&#xff1a; > Profile not found. Tried ~/.bashrc, ~/.bash_profile, ~/.zprofile, ~/.…

hi3516cv610构建音频sample工程代码步骤

hi3516cv610构建音频sample工程代码步骤 sdk版本&#xff1a;Hi3516CV610_SDK_V1.0.1.0 硬件&#xff1a;非es8388 工程代码&#xff1a; 通过网盘分享的文件&#xff1a;audio_easy.zip 链接: https://pan.baidu.com/s/1gx61S_F3-pf6hPyfbGaRXg 提取码: 4gbg --来自百度网盘…

12.QT-Combo Box|Spin Box|模拟点餐|从文件中加载选项|调整点餐份数(C++)

Combo Box QComboBox 表⽰下拉框 核⼼属性 属性说明currentText当前选中的⽂本currentIndex当前选中的条⽬下标.从0开始计算.如果当前没有条⽬被选中,值为-1editable是否允许修改设为true时, QComboBox 的⾏为就⾮常接近 QLineEdit ,也可以 设置 validatoriconSize下拉框图标…

UML 顺序图:电子图书馆管理系统的交互之道

目录 一、初识 UML 顺序图 二、电子图书馆管理系统顺序图解析 &#xff08;一&#xff09;借阅流程 &#xff08;二&#xff09;归还流程 三、顺序图绘画 四、顺序图的优势与价值 五、总结 UML 顺序图是描绘系统组件交互的有力工具。顺序图直观展示消息传递顺序与对象协…

访问者模式:分离数据结构与操作的设计模式

访问者模式&#xff1a;分离数据结构与操作的设计模式 一、模式核心&#xff1a;将操作从数据结构中分离&#xff0c;支持动态添加新操作 在软件开发中&#xff0c;当数据结构&#xff08;如树、集合&#xff09;中的元素类型固定&#xff0c;但需要频繁添加新的操作&#xf…

【AI训练环境搭建】在IDE(Pycharm或VSCode)上使用WSL2+Ubuntu22.04+Conda+Tensorflow+GPU进行机器学习训练

本次实践将在IDE&#xff08;Pycharm或VSCode&#xff09;上使用WSL2Ubuntu22.04TensorflowGPU进行机器学习训练。基本原理是在IDE中拉起WSL2中的Python解释器&#xff0c;并运行Python程序。要运行CondaTensorflowGPU你可能需要进行以下准备工作。 1. 此示例中将使用一个mnis…

Leetcode19(亚马逊真题):删除链表的倒是第N个节点

题目分析 删除节点关键&#xff1a;找到被删节点的前一个节点&#xff0c;指针指向 虚拟头节点&#xff0c;方便删除头结点&#xff0c;形成统一操作 为啥要让快指针先行&#xff1f; 我认为更好懂的一种解释&#xff1a;快指针先行n步&#xff0c;这样快慢指针之间形成了一…

Hadoop+Spark 笔记 2025/4/21

读书笔记 定义 1. 大数据&#xff08;Big Data&#xff09; - 指传统数据处理工具难以处理的海量、高速、多样的数据集合&#xff0c;通常具备3V特性&#xff08;Volume体量大、Velocity速度快、Variety多样性&#xff09;。扩展后还包括Veracity&#xff08;真实性&#x…

Redis从入门到实战基础篇

前言&#xff1a;Redis的安装包含在Redis从入门到实战先导篇中&#xff0c;需要的可移步至此节 目录 1.Redis简单介绍 2.初始Redis 2.1.认识NoSQL 2.2.认识Redis 2.3.安装Redis 3.Redis常见命令 3.1 Redis数据结构 3.2 通用命令 3.3 String命令 3.4 Key的层级结构 3…

Java虚拟机(JVM)家族发展史及版本对比

Java虚拟机&#xff08;JVM&#xff09;家族发展史及版本对比 一、JVM家族发展史 1. 早期阶段&#xff08;1996-2000&#xff09; Classic VM&#xff08;Java 1.0-1.1&#xff09;&#xff1a; 厂商&#xff1a;Sun Microsystems&#xff08;Oracle前身&#xff09;。特点&…

【学习笔记】Cadence电子设计全流程(三)Capture CIS 原理图绘制(下)

【学习笔记】Cadence电子设计全流程&#xff08;三&#xff09;Capture CIS 原理图绘制&#xff08;下&#xff09; 3.16 原理图中元件的编辑与更新3.17 原理图元件跳转与查找3.18 原理图常见错误设置于编译检查3.19 低版本原理图文件输出3.20 原理图文件的锁定与解锁3.21 Orca…

OpenCV 图形API(54)颜色空间转换-----将图像从 RGB 色彩空间转换到 HSV色彩空间RGB2HSV()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 将图像从 RGB 色彩空间转换为 HSV。该函数将输入图像从 RGB 色彩空间转换到 HSV。R、G 和 B 通道值的常规范围是 0 到 255。 输出图像必须是 8 位…