📣 独立日限时特惠: VIP通行证立减$68
回复: 25
跳转到指定楼层
上一主题 下一主题
收起左侧

LinkedIn System&Infra 两轮电面

全局:

2018(7-9月) 码农类General 硕士 实习@linkedin - 内推 - 技术电面  | | Other | 应届毕业生

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
第一轮:
collabedit状况百出,时不时就502 gateway not found。面的题是lc漆撕溜。面试官是印度人,跟他讲了思路(sliding window)他说最后一部分没有太听懂,然后先写代码。我彼边解释边写代码,写完之后本以为面试官对着代码可以看懂,结果竟然还是不懂。。。一开始我以为面试官只是在考察我对sliding window的理解,后来发现他是真的不懂。一
您好!
本帖隐藏的内容需要积分高于 188 才可浏览
您当前积分为 0。
使用VIP即刻解锁阅读权限或查看其他获取积分的方式
游客,您好!
本帖隐藏的内容需要积分高于 188 才可浏览
您当前积分为 0。
VIP即刻解锁阅读权限查看其他获取积分的方式
Unlock interview details and practice with AI
Curated Interview Questions from Top Companies

用户操作完以后会自动调用finish函数,将数组写入文件。


完全不知道怎么写,当时准备面经的时候也把这题给弃了。求会的人发个答案吧。

然后我直接跟面试官说我不会,就换成了lc散吧零,秒

两轮感觉都不是很好,发跪经一篇。

上一篇:LinkedIn System&Infra 两轮电面
下一篇:请问脸家实习二面约到12.12左右还会有坑吗?
推荐
magicsets 2017-12-4 06:54:42 | 只看该作者
全局:
1024 block的这道题目其实是一个比较简化的buffer manager组件,其中用来标记各个block有没有使用过的那部分数据一般称为meta data。

meta data使用什么数据结构其实可以比较灵活,但是最关键的一点是meta data本身也需要作为file的一部分能够被存储到disk上 —— 否则你下次读取那个文件就不知道哪些block被用过了。

很多(数据库)系统中,出于性能考虑,meta data都是直接映射到block上的,也就是使用block的memory定义数据结构——这需要手动进行内存管理——也就是你不能用malloc/new或是std::vector/std::list之类的去定义meta data。

另一个选项就是使用C++标准库中的数据结构(Java类同),然后在save/load的时候serialize/deserialize meta data。

这里贴一份样例代码,都是使用block memory进行手动内存管理的,有三种实现:
(1) bool 数组
(2) bit map
(3) 用一个recycle数组记录未被使用的block

其中(1)和(2)的allocate都是O(n)时间,(2)由于使用了builtin_clz所以会比(1)快很多——但是因为只有1024个blocks,所以也无所谓了...

(3)的allocate是O(1)时间,但是meta data耗用的空间会大一点(3个blocks)

  1. #include <array>
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <cstdlib>
  5. #include <cstring>
  6. #include <iostream>
  7. #include <memory>
  8. #include <stdexcept>

  9. constexpr std::size_t kBlockSize = 1024;
  10. constexpr std::size_t kNumBlocks = 1024;

  11. using BlockID = std::size_t;
  12. using Block = std::array<char, kBlockSize>;

  13. // abstract class
  14. class StorageManagerInterface {
  15. public:
  16.   virtual BlockID allocateNewBlock() = 0;

  17.   virtual void writeData(const BlockID block_id, const void *data) = 0;

  18.   virtual void deleteBlock(const BlockID block_id) = 0;
  19. };


  20. // 三种实现: bool array, bit map, free list

  21. // -----------------------------------------------------------------------------
  22. // 1. bool array
  23. // -----------------------------------------------------------------------------
  24. class ByteArrayMetaData {
  25. public:
  26.   ByteArrayMetaData(void *memory)
  27.       : status_(static_cast<bool*>(memory)),
  28.         capacity_(kNumBlocks - 1) {
  29.   }

  30.   std::size_t getNumOfBlocksUsed() const {
  31.     return 1;
  32.   }

  33.   BlockID alloc() {
  34.     for (std::size_t i = 0; i < capacity_; ++i) {
  35.       if (!status_[i]) {
  36.         status_[i] = true;
  37.         return i;
  38.       }
  39.     }
  40.     throw std::runtime_error("Out of blocks");
  41.   }

  42.   void free(const BlockID block_id) {
  43.     status_[block_id] = false;
  44.   }

  45. private:
  46.   bool *status_;
  47.   const std::size_t capacity_;
  48. };


  49. // 给bit map使用的一个辅助函数
  50. template <typename T>
  51. inline int LeadingZeroCount(T word);

  52. template <>
  53. inline int LeadingZeroCount<unsigned>(unsigned word) {
  54.   return __builtin_clz(word);
  55. }
  56. template <>
  57. inline int LeadingZeroCount<unsigned long>(unsigned long word) {
  58.   return __builtin_clzl(word);
  59. }
  60. template <>
  61. inline int LeadingZeroCount<unsigned long long>(unsigned long long word) {
  62.   return __builtin_clzll(word);
  63. }

  64. // -----------------------------------------------------------------------------
  65. // 2. bit map
  66. // -----------------------------------------------------------------------------
  67. class BitVectorMetaData {
  68. public:
  69.   BitVectorMetaData(void *memory)
  70.       : num_bits_(kNumBlocks - 1),
  71.         data_(static_cast<std::size_t*>(memory)),
  72.         data_size_((num_bits_ >> kHigherOrderShift) +
  73.                    (num_bits_ & kLowerOrderMask ? 1 : 0)) {
  74.   }

  75.   std::size_t getNumOfBlocksUsed() const {
  76.     return 1;
  77.   }

  78.   BlockID alloc() {
  79.     BlockID ret = num_bits_;
  80.     for (std::size_t i = 0; i < data_size_; ++i) {
  81.       const std::size_t code = ~data_[i];
  82.       if (code) {
  83.         const std::size_t offset = LeadingZeroCount<std::size_t>(code);
  84.         data_[i] |= kTopBit >> offset;
  85.         ret = (i << kHigherOrderShift) | offset;
  86.         break;
  87.       }
  88.     }
  89.     if (ret < num_bits_) {
  90.       return ret;
  91.     }
  92.     throw std::runtime_error("Out of blocks");
  93.   }

  94.   void free(const BlockID block_id) {
  95.     data_[block_id >> kHigherOrderShift] &= ~(kTopBit >> (block_id & kLowerOrderMask));
  96.   }

  97. private:
  98.   static constexpr std::size_t kLowerOrderMask = (sizeof(std::size_t) << 3) - 1;
  99.   static constexpr std::size_t kHigherOrderShift = sizeof(std::size_t) == 4 ? 5 : 6;
  100.   static constexpr std::size_t kTopBit = static_cast<std::size_t>(1) << kLowerOrderMask;

  101.   const std::size_t num_bits_;
  102.   std::size_t *data_;
  103.   const std::size_t data_size_;
  104. };


  105. // 3. free list
  106. class FreeListMetaData {
  107. public:
  108.   FreeListMetaData(void *memory)
  109.       : capacity_(kNumBlocks - CalculateNumBlocksUsed()) {
  110.     alloc_size_ = reinterpret_cast<std::uint16_t*>(memory);
  111.     recycle_size_ = alloc_size_ + 1;
  112.     recycle_list_ = recycle_size_ + 1;
  113.   }

  114.   std::size_t getNumOfBlocksUsed() const {
  115.     return CalculateNumBlocksUsed();
  116.   }

  117.   BlockID alloc() {
  118.     if (*recycle_size_ > 0) {
  119.       return recycle_list_[--(*recycle_size_)];
  120.     }
  121.     if (*alloc_size_ < capacity_) {
  122.       return (*alloc_size_)++;
  123.     }
  124.     throw std::runtime_error("Out of blocks");
  125.   }

  126.   void free(const BlockID block_id) {
  127.     recycle_list_[(*recycle_size_)++] = block_id;
  128.   }

  129. private:
  130.   static inline std::size_t CalculateNumBlocksUsed() {
  131.     const std::size_t total_bytes =
  132.         sizeof(std::uint16_t) +              // alloc_size_
  133.         sizeof(std::uint16_t) +              // recycle_size_
  134.         sizeof(std::uint16_t) * kNumBlocks;  // recycle_list_
  135.     return (total_bytes + kBlockSize - 1) / kBlockSize;
  136.   }

  137.   std::uint16_t *alloc_size_;
  138.   std::uint16_t *recycle_size_;
  139.   std::uint16_t *recycle_list_;
  140.   const std::size_t capacity_;
  141. };


  142. template <typename MetaData>
  143. class StorageManager : public StorageManagerInterface {
  144. public:
  145.   StorageManager() {
  146.     // 读取文件 -- 这里简化为malloc + 置0
  147.     stream_ = std::malloc(sizeof(Block) * kNumBlocks);
  148.     std::memset(stream_, 0, kNumBlocks * kBlockSize);

  149.     // 初始化meta data
  150.     meta_data_ = std::make_unique<MetaData>(stream_);

  151.     // 定位到数据区域
  152.     blocks_ = static_cast<Block*>(stream_) + meta_data_->getNumOfBlocksUsed();
  153.   }

  154.   BlockID allocateNewBlock() override {
  155.     return meta_data_->alloc();
  156.   }

  157.   void writeData(const BlockID block_id, const void *data) override {
  158.     std::memcpy(blocks_ + block_id, data, kBlockSize);
  159.   }

  160.   void deleteBlock(const BlockID block_id) override {
  161.     meta_data_->free(block_id);
  162.   }

  163. private:
  164.   void *stream_;
  165.   std::unique_ptr<MetaData> meta_data_;
  166.   Block *blocks_;
  167. };


  168. int main(int argc, char *argv[]) {
  169.   std::unique_ptr<StorageManagerInterface> storage_manager;

  170.   storage_manager = std::make_unique<StorageManager<ByteArrayMetaData>>();
  171. //  storage_manager = std::make_unique<StorageManager<BitVectorMetaData>>();
  172. //  storage_manager = std::make_unique<StorageManager<FreeListMetaData>>();

  173.   BlockID b1 = storage_manager->allocateNewBlock();
  174.   std::cout << "alloc b1 = " << b1 << "\n";

  175.   BlockID b2 = storage_manager->allocateNewBlock();
  176.   std::cout << "alloc b2 = " << b2 << "\n";

  177.   BlockID b3 = storage_manager->allocateNewBlock();
  178.   std::cout << "alloc b3 = " << b3 << "\n";

  179.   storage_manager->deleteBlock(b2);
  180.   std::cout << "delete b2\n";

  181.   BlockID b4 = storage_manager->allocateNewBlock();
  182.   std::cout << "alloc b4 = " << b4 << "\n";

  183.   BlockID b5 = storage_manager->allocateNewBlock();
  184.   std::cout << "alloc b5 = " << b5 << "\n";

  185.   return 0;
  186. }
复制代码



评分

参与人数 2大米 +11 收起 理由
AnthonyNeu + 10 给你点个赞!
xinxinzhenbang + 1 写的真是好

查看全部评分

回复

使用道具 举报

推荐
MacJordan 2017-12-1 13:47:16 | 只看该作者
全局:
第一题746吗?。。没有这题呀。。漆撕溜代指新题吗
回复

使用道具 举报

全局:
我的colabet也出了问题。
这个题据说是要把第一个block做成bitset, 每个byte标志一个block是否可用。
但我个人觉得这题更好的做法是每个block有header指向下一个free block, 类似15213的malloc lab。
回复

使用道具 举报

全局:
xinxinzhenbang 发表于 2017-12-1 13:04
我的colabet也出了问题。
这个题据说是要把第一个block做成bitset, 每个byte标志一个block是否可用。
但 ...

羡慕楼主可以做两个题,我只做一题真是凉凉。
回复

使用道具 举报

🔗
ivanyang 2017-12-1 13:14:07 | 只看该作者
全局:
xinxinzhenbang 发表于 2017-12-1 13:04
我的colabet也出了问题。
这个题据说是要把第一个block做成bitset, 每个byte标志一个block是否可用。
但 ...

collabedit 是真的垃圾.... 我面试的时候就没连上过... 直接换了Google doc...
回复

使用道具 举报

全局:
ivanyang 发表于 2017-12-1 13:14
collabedit 是真的垃圾.... 我面试的时候就没连上过... 直接换了Google doc...

我也是中途换了google doc
回复

使用道具 举报

🔗
wxl3691 2017-12-1 13:29:15 | 只看该作者
全局:
其实collabedit真的是好东西,代码不管对错都可以上,以后skype集成codepad成功后,就是对着视频看脸写代码还要编译通过,想想都觉得刺激。。。。。。。。。。。。。。。。。。
回复

使用道具 举报

🔗
valleyvalley 2017-12-1 13:35:21 | 只看该作者
全局:
我面的时候第一轮collabedit一直不sync..然后面试官直接开了一个codepad给我,然后第二轮collabedit直接down掉了打不开。。。又面试官自己开的codepad...codepad这么好用,不知道为什么要用collabedit。。。不过面试官说面完hr会找他们要collabedit的使用感受,估计被淘汰指日可待
回复

使用道具 举报

🔗
F4bwDP6a6WXkB 2017-12-1 13:58:43 | 只看该作者
全局:
1024 block 感觉和lc散吧零有点类似吧。能不能hashmap + array来解决,array里面存block的地址。每次删除一个block把array最后一个的数据移过来,然后把size - 1.  这是一种办法 还有一种就是 不swap数据,每次写的时候遍历一遍所有的block找到第一个为空的。不知道题意我是否理解正确了。
回复

使用道具 举报

🔗
 楼主| tigermlt 2017-12-1 14:46:16 | 只看该作者
全局:
xinxinzhenbang 发表于 2017-12-1 13:04
我的colabet也出了问题。
这个题据说是要把第一个block做成bitset, 每个byte标志一个block是否可用。
但 ...

这题有写好的代码可以参考一下吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表