logo

6.26 来腾讯三周,已经对大厂祛魅了

作者
Modified on
Reading time
6 分钟阅读:..评论:..

大家好,我是白露。 一个网友跟我分享说,来腾讯三周,已经对大厂祛魅了。

三周时间做的事情说多不多说少不少,由于mentor的职级已经是t10了,目前更多的是运维部署工作。 这位同学就跟着师兄完成了一些部署任务,修改了6个小缺陷,还做了一个小需求(数据迁移,主要是新建一个表和编写一些基础的增删改查操作)。 通过完成这些任务,他很快就了解到代码架构的样子。 然后发现代码规范没有我想象中的那么严格。hh 师兄说:“实现功能就行,怎么写都行。” 但是这好像,跟他上家公司实习的体验大不一样啊。虽说规模没腾讯大,但在很多细节上很严格。比如,新建一个数据表需要走审批和工单流程,获得批准后才可以去建表。 而在腾讯,师兄说只要建表时给他看一眼语句就行。另外,service调用store时也没有明确的分类限制,只要能实现功能就好。 不得不说,环境熟悉起来真的头大(因为大厂的东西太多了~)。大厂里的各种网站和术语多得让人晕头转向。 比如,代码合并不叫合并,而是叫“合流”,刚开始听到这些专有名词,真是很懵。 福利方面,各部门差别很大。 有些部门很养老,6点下班后还能吃个饭打个球;但有的部门10点下班甚至更晚。 他们部门似乎特别忙,健康日也不早下班,只有他6点吃了饭后下班去吃甜点。 团建活动更是如此,有的部门一个月两次小团建,而网友所在的部门已经两年没团建了。。。 一句话来说,腾讯的实习还算蛮舒服的。 师兄给的压力很小,他是独立工作的人,任务需要主动去要,或者让隔壁师兄分配。 隔壁师兄前年暑期转正,跟他交流起来效率很高。 不过,有一点让这位同学觉得不太满意,就是腾讯没有配发Mac笔记本,只有Windows台式机,感觉特别不方便。 哈哈,看了这位同学的经历,我想起了之前实验室同门师兄给我分享的,同一个组,负责不同的项目差别也很大,有的老项目还是用python写的 实验室的师兄之前是写C++的,他们组在把Python 改go 中,直接新学两种语法。。。那屎山代码头都大了。 另外,之前鱼皮在论坛里也分享过,同在大厂,不同小组的体验都是天差地别的,薪资年终、业务、日常工作、管理模式、卷的程度等等。 如果有小伙伴还在实习的话,觉得当前实习部门不好后面还可以争取换个部门。 今天我们就来看一次i腾讯的场景题面试,关注我,发送秋招提前批,就可以获取提前批资料了哦~

场景题目-Map

面试官: 同学你好,我们来讨论一下LRU缓存如果LRU缓存不用map指向迭代器会怎么样求职者: 如果LRU缓存不用map指向迭代器,会导致以下问题:

  • 查找效率低:每次需要查找一个元素时,必须从头遍历链表或数组,时间复杂度为O(n),而使用map查找时间复杂度为O(1)
  • 更新效率低:每次访问一个元素后,需要将其移动到表头或数组头部,这也需要遍历找到该元素,时间复杂度为O(n)

这样会显著降低LRU缓存的性能,特别是在高并发和高访问频率的场景下。 面试官: 那么,我们来分析一下数组实现和链表实现的缺陷。你能先说说数组实现的缺陷吗求职者: 当然。使用数组实现LRU缓存的主要缺陷有:

  • 固定大小:数组的大小是固定的,不容易扩展或缩减。
  • 插入和删除效率低:在数组头部插入或删除元素需要移动大量元素,时间复杂度为O(n)
  • 空间利用率低:预分配的数组空间可能会浪费,如果实际数据量远小于数组大小,会浪费内存资源。

这些缺陷使得数组在实现动态和频繁更新的LRU缓存时表现不佳。 面试官: 那么,链表实现又有哪些缺陷呢? 求职者: 使用链表实现LRU缓存的主要缺陷有:

  • 空间开销大:每个节点需要额外存储前驱和后继指针,占用更多内存。
  • 局部性差:链表节点在内存中可能不连续,访问时容易产生缓存未命中,降低访问速度。
  • 实现复杂:双向链表的插入和删除操作需要处理前驱和后继指针,容易出错,代码复杂度较高。

尽管链表在插入和删除操作上比数组更高效,但其空间开销和实现复杂度依然是不可忽视的问题。 面试官: 好的,我们再深入一点。假如我们要实现一个高效的LRU缓存,你会怎么做?能提供一个C++的实现吗? 求职者: 当然可以。高效的LRU缓存可以使用哈希表双向链表结合的方式来实现。哈希表用于快速查找,双向链表用于维护访问顺序。 以下是一个C++的实现示例:

#include <unordered_map> #include <list> class LRUCache { private: int capacity; std::list<std::pair<int, int>> cacheList; std::unordered_map<int, std::list<std::pair<int, int>>::iterator> cacheMap; public: LRUCache(int capacity) : capacity(capacity) {} int get(int key) { if (cacheMap.find(key) == cacheMap.end()) { return -1; } cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]); return cacheMap[key]->second; } void put(int key, int value) { if (cacheMap.find(key) != cacheMap.end()) { cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]); cacheMap[key]->second = value; return; } if (cacheList.size() == capacity) { int delKey = cacheList.back().first; cacheList.pop_back(); cacheMap.erase(delKey); } cacheList.emplace_front(key, value); cacheMap[key] = cacheList.begin(); } };

面试官: 请解释一下你的代码。 求职者:

  • capacity:缓存的容量。
  • cacheList:双向链表,存储缓存内容,最新访问的在前。
  • cacheMap:哈希表,键为缓存键,值为链表节点的迭代器,用于快速定位缓存项。

get操作

  • 查找:在cacheMap中查找键,若不存在返回-1。
  • 移动到头部:若存在,将对应的链表节点移动到链表头部。
  • 返回值:返回缓存值。

put操作

  • 更新:若键已存在,更新值并移动到链表头部。
  • 插入:若键不存在,先检查缓存是否已满,若满则删除链表尾节点和对应的哈希表项,然后在链表头部插入新节点,并更新哈希表。

这样就能高效地实现LRU缓存,保证了**O(1)**的时间复杂度进行查找和更新操作。 面试官: 很好,今天的面试就到这里了,感谢你的回答。我们会尽快通知你结果。