当前位置: 首页 > news >正文

【面试题】大厂高压面经实录丨第二期

C++数据结构篇

大厂高压面经实录,结合腾讯、阿里、字节等真实技术面试场景,包含压迫式追问核心陷阱代码实战,助你彻底碾压面试官:


⚡️ 一、Top K问题:堆 vs 快速选择(字节跳动3面原题)

面试官​(打断式追问):“10亿整数找Top 100,内存限制1GB,5分钟内手撕代码,禁用第三方库!”
大厂级应答​:

  1. 最小堆解法(海量数据唯一正解)

#include <queue>
#include <vector>
std::vector<int> topK(std::vector<int>& nums, int k) {std::priority_queue<int, std::vector<int>, std::greater<int>> min_heap; // 最小堆for (int num : nums) {if (min_heap.size() < k) {min_heap.push(num);} else if (num > min_heap.top()) {min_heap.pop();min_heap.push(num); // 淘汰堆顶,加入新元素}}// 转存结果(注意:堆中是无序的)std::vector<int> res;while (!min_heap.empty()) {res.push_back(min_heap.top());min_heap.pop();}return res;
}

性能关键点​:

  • 时间复杂度:O(n log k)
  • 空间复杂度:O(k)(仅需常驻100个元素)
  • 陷阱​:若用最大堆全排序 → 内存爆炸 O(n)

2.​快速选择(面试加分项)

int partition(std::vector<int>& nums, int left, int right) {int pivot = nums[right];int i = left;for (int j = left; j < right; ++j) {if (nums[j] >= pivot) std::swap(nums[i++], nums[j]); // 注意:降序排列}std::swap(nums[i], nums[right]);return i;
}void quickSelect(std::vector<int>& nums, int left, int right, int k) {if (left >= right) return;int pos = partition(nums, left, right);if (pos == k) return;else if (pos < k) quickSelect(nums, pos + 1, right, k);else quickSelect(nums, left, pos - 1, k);
}

致命细节​:

  • 平均 O(n),但需处理最坏情况​(如全有序时退化为 O(n²)) → 必须随机化基准值
std::swap(nums[right], nums[left + rand() % (right - left + 1)]); // 随机选择基准

🌳 二、二叉树序列化与反序列化(腾讯T9手撕代码)

面试官​(甩白板):“支持带空指针的任意结构,写代码实现二叉树↔字符串双向转换!”
避坑实现​:

// 序列化(前序遍历)
std::string serialize(TreeNode* root) {if (!root) return "#,";return std::to_string(root->val) + "," + serialize(root->left) + serialize(root->right);
}// 反序列化
TreeNode* deserialize(std::string data) {std::istringstream ss(data);return buildTree(ss);
}TreeNode* buildTree(std::istringstream& ss) {std::string token;std::getline(ss, token, ',');if (token == "#") return nullptr;TreeNode* root = new TreeNode(std::stoi(token));root->left = buildTree(ss);root->right = buildTree(ss);return root;
}

字节跳动死亡追问​:

  1. 为什么不用中序?​​ → 中序无法确定根位置,序列化结果歧义(反例:1,#,2 可对应多种结构)
  2. 空间如何优化?​​ → 用层序遍历替代前序(避免递归栈溢出)
  3. 内存泄漏风险​ → 面试中需主动补充析构函数!

📦 三、LRU缓存设计(阿里P8限时手撕)

面试官​:“5分钟实现O(1)的get/put,写错一行代码直接挂!”
工业级答案​:

#include <unordered_map>
#include <list>
class LRUCache {
private:struct Node { int key, val; };std::list<Node> cache; // 双向链表:存储节点std::unordered_map<int, std::list<Node>::iterator> map; // 哈希表:key->链表迭代器int capacity;
public:LRUCache(int cap) : capacity(cap) {}int get(int key) {if (!map.count(key)) return -1;auto it = map[key];cache.splice(cache.end(), cache, it); // 关键:移动节点到链表尾部(表示最近使用)return it->val;}void put(int key, int value) {if (map.count(key)) {auto it = map[key];it->val = value; // 更新值cache.splice(cache.end(), cache, it);return;}if (cache.size() == capacity) { // 淘汰队头map.erase(cache.front().key);cache.pop_front();}cache.push_back({key, value});map[key] = std::prev(cache.end());}
};

腾讯终面拷问​:

  • 为什么必须用双向链表?​​ → 单链表无法O(1)删除中间节点(需遍历找前驱)
  • 线程安全如何实现?​​ → 答:用读写锁(std::shared_mutex)保护链表和哈希表

🔍 四、图论:拓扑排序检测环(华为自动驾驶团队真题)

面试官​:“百万节点任务依赖图,实时判断是否成环,系统要求高并发低延迟!”
分布式级方案​:

#include <vector>
#include <queue>
bool hasCycle(int n, std::vector<std::vector<int>>& graph) {std::vector<int> indegree(n, 0);std::queue<int> q;// 计算入度for (int i = 0; i < n; ++i) for (int neighbor : graph[i]) indegree[neighbor]++;// 入度0节点入队for (int i = 0; i < n; ++i)if (indegree[i] == 0) q.push(i);int count = 0;while (!q.empty()) {int node = q.front(); q.pop();count++;for (int neighbor : graph[node]) {if (--indegree[neighbor] == 0) q.push(neighbor);}}return count != n; // 存在环时count < n
}

字节跳动加问​:

  • 如何并行化?​​ → 分片计算入度(如按节点ID哈希分片),合并结果(atomic同步)
  • DFS染色法缺点​ → 递归深度大时栈溢出,且无法增量更新

⚙️ 五、哈希表:高并发优化(美团中间件团队终面)

面试官​:“线上服务哈希表扩容卡顿10秒,引发雪崩!不许重启,如何急救?”
T9架构师方案​:

  1. 渐进式Rehash(Redis同款)
class ProgressiveHashMap {std::vector<std::unordered_map<int, int>> tables{2}; // 新旧双表int rehash_idx = -1; // -1表示未在rehashvoid rehashStep() {if (rehash_idx < 0) return;auto& old_table = tables[0];auto& new_table = tables[1];// 每次迁移1个桶auto it = old_table.begin();std::advance(it, rehash_idx);new_table.insert(*it);old_table.erase(it);rehash_idx++;if (rehash_idx >= old_table.size()) {tables[0] = std::move(tables[1]); // 迁移完成rehash_idx = -1;}}
public:void put(int key, int val) {if (rehash_idx >= 0) rehashStep(); // 每次操作迁移一桶// ... 正常插入逻辑}
};

2.​替代分配器降低碎片

LD_PRELOAD="/usr/lib/libtcmalloc.so" ./my_program # 加载tcmalloc

  1. 性能对比​:
    方案平均延迟碎片率
    glibc malloc120ms
    tcmalloc35ms低70%
    渐进式Rehash<1ms波动趋近0

💎 大厂面试终极技巧

  1. 数据结构选择铁律​:
    • 随机访问 → vector(连续内存+缓存友好)
    • 高频插入删除 → listO(1)节点操作)
    • 快速查找 → unordered_map(哈希表)或 map(红黑树有序)
  2. 代码手撕三大原则​:
    • 先写边界条件(空输入、容量满等)
    • 主动检测内存泄漏(智能指针/析构函数)
    • 时间复杂度必须脱口而出
  3. 反杀追问话术​:

    “我设计的LRU时间复杂度是O(1),因为哈希表查找O(1),链表移动节点也是O(1)。您担心线程安全问题?可以引入分段锁,但读多写少场景更推荐std::shared_mutex...”

来自阿里P9的忠告​:
区分普通码农和架构师的核心——普通玩家背答案,高端玩家能改造STL容器,地狱玩家手写内存分配器。”

 ​资源直通​:

戳这里>>「」获取以下资源:

  1. 《C++后端开发高频八股文》
    涵盖23个核心考点,助你轻松应对面试!

  2. 《C/C++工程师能力自测清单》
    50+项技能树Checklist,快速定位技术短板!

  3. 【开源项目】libevent-master
    高性能网络库源码,深入理解事件驱动编程!

  4. 【开源项目】workflow-master
    现代C++异步任务调度框架,提升开发效率!

  5. 《LeetCode 101算法精讲》
    剑指Offer最优解合集,算法刷题必备神器!

关注我,获取更多C++硬核知识! 🚀

http://www.dtcms.com/a/286017.html

相关文章:

  • Jmeter系列(6)-测试计划
  • 【工具变量】地级市人力资本测算数据集(1990-2024年)
  • 近期遇到的问题汇总
  • 【48】MFC入门到精通——MFC 文件读写总结 CFile、CStdioFile、CFileDialog
  • SpringCloud相关总结
  • [论文阅读] 人工智能 + 软件工程 | 单会话方法论:一种以人类为中心的人工智能辅助软件开发协议
  • oracle 11.2.0.4 RAC下执行root.sh脚本报错
  • 2025年UDP应用抗洪指南:从T级清洗到AI免疫,实战防御UDP洪水攻击
  • 【Apache Paimon】-- 1.2.0 版本的Table 类型和 merge engine
  • JAVA 使用Apache POI合并Word文档并保留批注的实现
  • 近期学习过程问题整理
  • Java学习------ConcurrentHashMap
  • Spring底层(二)Spring IOC容器加载流程原理
  • PermissionError: [Errno 13] Permission denied
  • 复盘爬虫课后练习题
  • 前端学习8:JavaScript数据类型|声明变量|函数定义|函数参数|作用域(多个小练习上手)
  • 【三维重建】LODGE:谷歌DeepMind发布大场景超快3DGS!分层渲染,移动设备均可!
  • CentOS7 内网服务器yum修改
  • 金属伪影校正的双域联合深度学习框架复现
  • blender如何队列渲染多个工程文件的动画?
  • 声画同步!5 个音视频素材适配的网站,创作更和谐
  • 算法学习笔记:29.拓扑排序——从原理到实战,涵盖 LeetCode 与考研 408 例题
  • 前端埋坑之js console.log字符换行后 html没换行问题处理
  • HTML 页面禁止缩放功能
  • javascript 中数组对象操作方法
  • Paimon对比基于消息队列(如Kafka)的传统实时数仓方案的优势
  • Kafka的基本使用
  • 关于在VScode中使用git的一些步骤常用命令及其常见问题:
  • MariaDB 10.4.34 安装配置文档(Windows 版)
  • LLM(Large Language Model)大规模语言模型浅析