高频手撕
数据结构与算法·面试高频 · 第 5 章 现场手撕题
按 空格/→ 演示下一步
全部页面点击任意一页,跳回舞台从这页播放
高频手撕
数据结构与算法·面试高频 · 第 5 章 现场手撕题
线程交替打印
两个线程交替打 0~n:轮次条件、互斥锁、通知三件套,一个都不能少。
奇偶交替打印
轮次判断加锁与通知,经典同步协奏曲。
wait 释放锁并挂起,notifyAll 唤醒后重竞争;while 复查防虚假唤醒。交替的关键是「轮次 + 锁 + 通知」三件套。
生产者消费者
缓冲区解耦两端:满则生产者等,空则消费者等,互斥锁配两个条件。
有界阻塞缓冲区
synchronized 管互斥,while 加 wait 管条件。
互斥由方法锁保证,条件由 while 加 wait 保证,notifyAll 广播防漏醒。这就是信号量 P/V 操作的对象版。
线程安全单例
双重检查锁的经典考题:volatile 禁重排,synchronized 只锁第一次。
双重检查锁单例
一检免锁、二检唯一、volatile 禁重排。
一检让常态调用免锁,二检防并发重复创建;volatile 保证实例构造完成后其他线程才可见。
令牌桶限流器
匀速放令牌,请求拿牌通行:桶定容量,按流逝时间补牌,平滑限流。
惰性补牌的令牌桶
不来请求不算账,来了按流逝时间补齐。
惰性补牌免去后台线程:补牌量 = 流逝时间 × 速率,封顶桶容量。容量即突发上限,速率即长期均值。
手写深拷贝
深拷贝即递归克隆:基本类型照抄,对象下钻,循环引用靠备忘录。
带备忘录的深拷贝
递归下钻 + 备忘录,循环引用也不怕。
seen 备忘录是循环引用的解药:a.self = a 也不会死循环;Date、Map 等类型按需补充分支即可。
LRU 完整实现
哈希表加双向链表:get/put 都是 O(1),链表管次序,哈希管直达。
LRU 缓存
借助语言内置的有序结构,答案简洁不扣分。
用内置有序结构是合法答案;被要求手写时再展开双向链表版——核心都是「O(1) 定位加 O(1) 摘除插入」。
本节要点
- ✓交替打印:轮次、锁、通知三件套
- ✓生产者消费者:互斥加双条件
- ✓单例:双重检查配 volatile
- ✓LRU:哈希直达,链表定序
课后思考
先自己回答,再展开参考答案——能讲出来才算真懂。
参考答案存在虚假唤醒,以及醒来时条件已被别的线程抢走的情形;被唤醒后必须复查条件,不满足继续等。while 是唯一安全的写法。
参考答案漏桶恒定速率出水,强制平滑、不允突发;令牌桶按速率积累、桶容量放行突发——长期均值受限而瞬时可达容量。按业务对突发的容忍度选型。
参考答案哈希表负责「有没有、在哪」,双向链表负责「新旧次序」:定位后摘链、插头都是 O(1)。单一结构做不到,组合才能两全。