已拿offer!2024届校招抖音电商提前批面试问题及参考答案!

C语言与CPP编程 2023-09-09 08:30

r

南京夫子庙茶颜悦色店 摄于2023.8.27

大家好,我是飞宇。

今天分享一份校招面试面经问题和答案,希望对大家有所帮助!分享人是一位2024届的学弟,投递岗位为字节跳动抖音电商部门,考察语言主要为C/C++、Golang以及其余计算机基础知识等。

最近李伟老师讲了《C++ Primer 5th》这本书的视频,他是美国微软高级工程师,清华大学博士,帮忙推广一下,感兴趣的可以看看。

互联网圈有个梗就是"两大码农工厂:南华科、北北邮",就是说这两所高校的毕业生从事互联网工作的特别多,北邮虽然是211,但在互联网圈子里比很多985学校的牌子都好使,一些互联网公司甚至有北邮帮的说法,你的组长甚至leader搞不好都是你的往届学长

以前就聊过不建议普通人随便去提前批随便面试这个话题:再次认真聊一聊,为什么我建议你不要随大流去参加提前批?,但北邮本硕的学历背景 + 2段大厂实习在手,肯定不是普通人了,这个含金量还是很够的,加上后台有人私信留言问有没有提前批上岸的经验,今天就来分享一下一位师弟的提前批上岸面经。

抖音电商面试一共是三轮技术面+一轮HR面,一共超过 40 个问题,我系统整理了一遍,并将其中一些比较不错的问题,摘录到了自己开发的网站上。

InterviewGuide大厂面试真题网站:https://top.interviewguide.cn

今天把师弟的三轮技术面经按照科目分享一下其中的编程语言和算法类的问题,计算机基础知识问题考察明天再发,因为篇幅太长了,一次发估计很多人都看不完,希望这些内容能对大家有帮助。

以下是这位师弟的面经以及部分参考答案:


大家好,应大佬邀请,我来分享一下自己的面经。

简单介绍一下自己的背景,北邮计算机本硕,目前研二在读,以前本科毕业后gab过一年,工作一年后又来读研了,目前B站+百度分别实习了三个月,我本来打算在B站一直实习下去的,但后来请教了秀哥,秀哥建议我换一家体量更大的公司继续实习,两段实习还是比一家强,后来就跑去百度实习了。

自己能在提前批拿到offer也没想到,原本以为自己是直接挂的,但没想到上岸了,最开始是不打算找提前批的,但秀哥建议我去试试,不要浪费自己的学历背景+实习经历,我就像被打了鸡血一样就去试了。

可能是踩了狗屎运,居然上岸了。

下面是我的面经,我是C++/Golang双语言技术栈,其实我最开始是学习C++的,后来在B站实习时接触到Go语言,后来就学了Go语言,变成双语言技术栈了。

C++

1、问:看你又会C++又会Golang,哪门语言了解的多一些?

:主要是C++,Go是在B站实习期间学习的,当时主要是为了做业务,很多细节都没怎么用心学,后面才慢慢补上的。

2、问:如何学习C++的?看过哪些书?

:主要是《C++ Primer 5th》、《Effective C++》、《More Effective C++》、《深度探索C++对象模型》、《ST源码剖析》以及《C++并发编程实践》,主要是这几本书。

3、问:move语义了解吗?有什么作用?

:move语义是一种高效的资源转移机制,实现移动语义,可以帮助我们避免不必要的拷贝操作,提高程序性能,显著提高效率。

阿秀补充

1、std::move的使用场景

当需要将资源从一个对象转移到另一个对象时,可以使用std::move。例如,在容器中移动元素、在算法中交换数据等。需要注意的是,只有可移动的对象才能使用移动语义,否则可能导致未定义行为。

2、避免不必要的拷贝

使用移动语义可以避免不必要的拷贝操作,从而提高性能。例如,在复制一个大型对象时,如果使用移动语义,只需要进行一次内存分配和一次指针拷贝,而不需要进行多次拷贝操作。

3、以下是C++中move语义的一些关键点:

移动构造函数:std::move可以将一个左值转换为右值引用,从而实现资源的转移。例如:

class MyClass {
public:
   MyClass(int x) : data(new int(x)) {}
   // 移动构造函数
   MyClass(MyClass&& other) noexcept : data(other.data) {
       other.data = nullptr;
   }
private:
   int* data;
};

移动赋值运算符:std::move也可以用于将一个对象的资源转移到另一个对象。例如:

MyClass a(1);
MyClass b(std::move(a)); // 使用std::move实现移动赋值

4、问:说一下程序的内存分区?

:从高地址和低地址分别向中间拓展,由上而下分别是堆、栈、自由存储区、全局/静态存储区、常量存储区和代码区。

阿秀补充

:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限

:就是那些由 new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个 delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收

自由存储区:如果说堆是操作系统维护的一块内存,那么自由存储区就是C++中通过new和delete动态分配和释放对象的抽象概念。需要注意的是,自由存储区和堆比较像,但不等价。

全局/静态存储区:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量和静态变量又分为初始化的和未初始化的,在C++里面没有这个区分了,它们共同占用同一块内存区,在该区定义的变量若没有初始化,则会被自动初始化,例如int型变量自动初始为0。

常量存储区:这是一块比较特殊的存储区,这里面存放的是常量,不允许修改

代码区:存放函数体的二进制代码

5、问:C++11中的新特性说说?

:老八股文了balabalab

阿秀补充

C++11新特性主要有:

  • nullptr替代 NULL
  • 引入了 auto 和 decltype 这两个关键字实现了类型推导
  • 基于范围的 for 循环for(auto& i : res){}
  • 类和结构体的中初始化列表
  • Lambda 表达式(匿名函数)
  • std::forward_list(单向链表)
  • 右值引用和move语义
  • 无序容器和正则表达式
  • 成员变量默认初始化
  • 智能指针等

6、问:auto是怎么实现识别自动类型的?

:不太清楚,回答了个“只知道是根据初始化表达式自动推导出变量的类型”的

阿秀补充

auto在C++11中是一种新的类型说明符,它可以根据初始化表达式自动推导出变量的类型。

auto的工作原理是:

  • 编译器看到auto,会查看初始化表达式的类型,并将该类型作为auto变量的类型。
  • 如果初始化表达式的类型可以确定,则使用该类型。如果初始化表达式包含了多个类型,则使用与初始化表达式兼容的共同类型。
  • 如果无法确定类型,则报错。

例如:

cpp auto x = 5; // x是int类型 
auto y = 1.5; // y是double类型 
auto z = x + y; // z是double类型 

std::vector<int> 
vec; auto itr = vec.begin(); // itr是std::vector<int>::iterator类型 

在上面例子中,编译器通过查看初始化表达式的类型,推导出auto变量的实际类型。

需要注意的是,auto只在声明时确定一次变量类型,之后变量类型不再改变,并且auto变量必须初始化,才能推导出类型。

7、问:模板是怎么实现转化成不同类型的?

:不懂呜呜呜

阿秀补充

模板是一种通用的编程技术,可以用于实现泛型编程,即编写一个通用的类或函数,可以适用于多种不同的数据类型。

在C++中,模板是通过模板参数来实现的。模板参数可以是一个类型、一个整数或者一个枚举类型。在使用模板时,需要为每个要使用的类型提供一个对应的模板参数。

参考代码:

template 
class MyClass {
public:
    void setValue(T value) {
        this->value = value;
    }

    T getValue() const {
        return value;
    }

private:
    T value;
};

8、问:push_back和emplace_back的区别?

:这个我知道,emplace_back通常在性能上优于push_back,可以避免不必要的复制或移动操作。

  • push_back() 向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素)
  • emplace_back() 在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。

9、问:刚才你说看过C++并发编程实战,那写个题吧,很简单的,创建三个线程,依次打印1到100.

:很常见的题,用thread就可以做,5分钟搞定!

这里阿秀补充一个无序版本的线程打印

#include 
#include 
using namespace std;

void print_nums(int start, int end) {
    for (int i = start; i <= end; i++) {
        cout << i << " ";
    }
    cout << endl;
}

int main() {
    thread t1(print_nums, 1, 25); // 创建第一个线程,打印1到25
    thread t2(print_nums, 26, 50); // 创建第二个线程,打印26到50
    thread t3(print_nums, 51, 100); // 创建第三个线程,打印51到100

    t1.join(); // 等待第一个线程执行完毕
    t2.join(); // 等待第二个线程执行完毕
    t3.join(); // 等待第三个线程执行完毕

    return 0;
}

Golang

10、问:看你在B站实习用的是Go语言是吧?怎么学的?

:我是直接看的github上的go语言极简入门,后来又看了《Go语言设计与实现》

11、问:问你一个简单的问题,你应该知道map是无序的,每次迭代map的顺序可能不同。如果需要按特定顺序遍历map,应该怎么做呢?

:可以考虑借助切片来做,将键保存在切片中,然后把切片排序,最后根据排序后的顺序遍历map访问对应的值,这样可以达到目的。

阿秀补充

package main

import (
 "fmt"
 "sort"
)

func main() {
 m := map[string]int{
  "b": 2,
  "a": 1,
  "c": 3,
 }

 keys := make([]string, 0, len(m))
 for k := range m {
  keys = append(keys, k)
 }

 sort.Strings(keys)

 for _, k := range keys {
  fmt.Println(k, m[k])
 }
}

12、问:你刚才提到了排序是吧,一般用sort函数,其中的排序函数是什么排序?

:内容os:这个我还真研究过。应该是快排、插入排序、堆排这三种,具体来说sort()源码中采用的是一种叫做IntroSort内省式排序的混合式排序算法,简单来说就是数据量达到一定规模就用快排或者堆排,没达到就用插入排序,但这个规模量我记不清了,大概是这个意思;快排和堆排的取舍则是根据最新递归深度的阈值来判断的。

阿秀补充

IntroSort内省式排序的混合式排序算法,

  • 第一步,首先进行判断排序的元素个数是否大于stl_threshold,stl_threshold是一个常量值是16,意思就是说我传入的元素规模小于我们的16的时候直接采用插入排序。

(为什么用插入排序?因为插入排序在面对“几近排序”的序列时,表现更好,而快排是通过递归实现的,会为了极小的子序列产生很多的递归调用在区间长度小的时候经常不如插入排序效率高)

  • 第二步,如果说我们的元素规模大于16,那就需要去判断如果是不是能采用快速排序,怎么判断呢?快排是使用递归来实现的,如果说我们进行判断我们的递归深度有没有到达递归深度的限制阈值2*lg(n),如果递归深度没达到阈值就使用快速排序来进行排序

  • 第三步,如果说大于我们的最深递归深度阈值的话,这个时候说明快排复杂度退化了(比如很不巧基准元素多次选取到了当前区间中最小或最大的元素。这种情况下,每次划分只能将区间缩小1个元素,造成递归深度过深),就会采用我们的堆排序,堆排序是可以保证稳定O(nlogn)的时间复杂度的。

13、问:如何移除切片中的数据?你有哪些方式?

:切片的切片操作或者append都可以。

阿秀补充

append这个简单,切片的切片其实就是使用切片的切片操作将切片分为两部分,将想要移除的元素从中间移除即可,比如我想移除第三个元素:

package main

import "fmt"

func main() {
    numbers := []int{1, 2, 3, 4, 5}
    index := 2
    numbers = append(numbers[:index], numbers[index+1:]...)
    fmt.Println(numbers) // 输出: [1 2 4 5]
}

算法

一共考察了4道题,一面2道,二面2道,三面没考,有剑指offer原题,也有力扣原题和变形题,都不算难,感觉刷力扣刷 500+ 以上都能顺利做出来。

盛最多水的容器:https://top.interviewguide.cn/issue/665

输出二叉树的左视图:https://top.interviewguide.cn/issue/697

链表判断有没有环:https://top.interviewguide.cn/issue/715

二叉树转双向链表:https://top.interviewguide.cn/issue/720

实习/项目

:介绍下你的两段实习经历?

:有什么收获?

EOF

你好,我是飞宇,本硕均于某中流985 CS就读,先后于百度搜索以及字节跳动电商等部门担任Linux C/C++后端研发工程师。

同时,我也是知乎博主@韩飞宇,日常分享C/C++、计算机学习经验、工作体会,欢迎点击此处查看我以前的学习笔记&经验&分享的资源。

我组建了一些社群一起交流,群里有大牛也有小白,如果你有意可以一起进群交流。

欢迎你添加我的微信,我拉你进技术交流群。此外,我也会经常在微信上分享一些计算机学习经验以及工作体验,还有一些内推机会

加个微信,打开另一扇窗

C语言与CPP编程 C语言/C++开发,C语言/C++基础知识,C语言/C++学习路线,C语言/C++进阶,数据结构;算法;python;计算机基础等
评论
  • 本文介绍瑞芯微开发板/主板Android配置APK默认开启性能模式方法,开启性能模式后,APK的CPU使用优先级会有所提高。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。源码修改修改源码根目录下文件device/rockchip/rk3562/package_performance.xml并添加以下内容,注意"+"号为添加内容,"com.tencent.mm"为AP
    Industio_触觉智能 2025-01-17 14:09 164浏览
  • 嘿,咱来聊聊RISC-V MCU技术哈。 这RISC-V MCU技术呢,简单来说就是基于一个叫RISC-V的指令集架构做出的微控制器技术。RISC-V这个啊,2010年的时候,是加州大学伯克利分校的研究团队弄出来的,目的就是想搞个新的、开放的指令集架构,能跟上现代计算的需要。到了2015年,专门成立了个RISC-V基金会,让这个架构更标准,也更好地推广开了。这几年啊,这个RISC-V的生态系统发展得可快了,好多公司和机构都加入了RISC-V International,还推出了不少RISC-V
    丙丁先生 2025-01-21 12:10 112浏览
  • 现在为止,我们已经完成了Purple Pi OH主板的串口调试和部分配件的连接,接下来,让我们趁热打铁,完成剩余配件的连接!注:配件连接前请断开主板所有供电,避免敏感电路损坏!1.1 耳机接口主板有一路OTMP 标准四节耳机座J6,具备进行音频输出及录音功能,接入耳机后声音将优先从耳机输出,如下图所示:1.21.2 相机接口MIPI CSI 接口如上图所示,支持OV5648 和OV8858 摄像头模组。接入摄像头模组后,使用系统相机软件打开相机拍照和录像,如下图所示:1.3 以太网接口主板有一路
    Industio_触觉智能 2025-01-20 11:04 150浏览
  • 2024年是很平淡的一年,能保住饭碗就是万幸了,公司业绩不好,跳槽又不敢跳,还有一个原因就是老板对我们这些员工还是很好的,碍于人情也不能在公司困难时去雪上加霜。在工作其间遇到的大问题没有,小问题还是有不少,这里就举一两个来说一下。第一个就是,先看下下面的这个封装,你能猜出它的引脚间距是多少吗?这种排线座比较常规的是0.6mm间距(即排线是0.3mm间距)的,而这个规格也是我们用得最多的,所以我们按惯性思维来看的话,就会认为这个座子就是0.6mm间距的,这样往往就不会去细看规格书了,所以这次的运气
    wuliangu 2025-01-21 00:15 186浏览
  • 日前,商务部等部门办公厅印发《手机、平板、智能手表(手环)购新补贴实施方案》明确,个人消费者购买手机、平板、智能手表(手环)3类数码产品(单件销售价格不超过6000元),可享受购新补贴。每人每类可补贴1件,每件补贴比例为减去生产、流通环节及移动运营商所有优惠后最终销售价格的15%,每件最高不超过500元。目前,京东已经做好了承接手机、平板等数码产品国补优惠的落地准备工作,未来随着各省市关于手机、平板等品类的国补开启,京东将第一时间率先上线,满足消费者的换新升级需求。为保障国补的真实有效发放,基于
    华尔街科技眼 2025-01-17 10:44 221浏览
  •  万万没想到!科幻电影中的人形机器人,正在一步步走进我们人类的日常生活中来了。1月17日,乐聚将第100台全尺寸人形机器人交付北汽越野车,再次吹响了人形机器人疯狂进厂打工的号角。无独有尔,银河通用机器人作为一家成立不到两年时间的创业公司,在短短一年多时间内推出革命性的第一代产品Galbot G1,这是一款轮式、双臂、身体可折叠的人形机器人,得到了美团战投、经纬创投、IDG资本等众多投资方的认可。作为一家成立仅仅只有两年多时间的企业,智元机器人也把机器人从梦想带进了现实。2024年8月1
    刘旷 2025-01-21 11:15 399浏览
  • 临近春节,各方社交及应酬也变得多起来了,甚至一月份就排满了各式约见。有的是关系好的专业朋友的周末“恳谈会”,基本是关于2025年经济预判的话题,以及如何稳定工作等话题;但更多的预约是来自几个客户老板及副总裁们的见面,他们为今年的经济预判与企业发展焦虑而来。在聊天过程中,我发现今年的聊天有个很有意思的“点”,挺多人尤其关心我到底是怎么成长成现在的多领域风格的,还能掌握一些经济趋势的分析能力,到底学过哪些专业、在企业管过哪些具体事情?单单就这个一个月内,我就重复了数次“为什么”,再辅以我上次写的:《
    牛言喵语 2025-01-22 17:10 41浏览
  • Ubuntu20.04默认情况下为root账号自动登录,本文介绍如何取消root账号自动登录,改为通过输入账号密码登录,使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持OpenHarmony5.0及Linux、Android等操作系统,接口丰富,开发评估快人一步!添加新账号1、使用adduser命令来添加新用户,用户名以industio为例,系统会提示设置密码以及其他信息,您可以根据需要填写或跳过,命令如下:root@id
    Industio_触觉智能 2025-01-17 14:14 122浏览
  •     IPC-2581是基于ODB++标准、结合PCB行业特点而指定的PCB加工文件规范。    IPC-2581旨在替代CAM350格式,成为PCB加工行业的新的工业规范。    有一些免费软件,可以查看(不可修改)IPC-2581数据文件。这些软件典型用途是工艺校核。    1. Vu2581        出品:Downstream     
    电子知识打边炉 2025-01-22 11:12 53浏览
  •  光伏及击穿,都可视之为 复合的逆过程,但是,复合、光伏与击穿,不单是进程的方向相反,偏置状态也不一样,复合的工况,是正偏,光伏是零偏,击穿与漂移则是反偏,光伏的能源是外来的,而击穿消耗的是结区自身和电源的能量,漂移的载流子是 客席载流子,须借外延层才能引入,客席载流子 不受反偏PN结的空乏区阻碍,能漂不能漂,只取决于反偏PN结是否处于外延层的「射程」范围,而穿通的成因,则是因耗尽层的过度扩张,致使跟 端子、外延层或其他空乏区 碰触,当耗尽层融通,耐压 (反向阻断能力) 即告彻底丧失,
    MrCU204 2025-01-17 11:30 182浏览
  • 数字隔离芯片是一种实现电气隔离功能的集成电路,在工业自动化、汽车电子、光伏储能与电力通信等领域的电气系统中发挥着至关重要的作用。其不仅可令高、低压系统之间相互独立,提高低压系统的抗干扰能力,同时还可确保高、低压系统之间的安全交互,使系统稳定工作,并避免操作者遭受来自高压系统的电击伤害。典型数字隔离芯片的简化原理图值得一提的是,数字隔离芯片历经多年发展,其应用范围已十分广泛,凡涉及到在高、低压系统之间进行信号传输的场景中基本都需要应用到此种芯片。那么,电气工程师在进行电路设计时到底该如何评估选择一
    华普微HOPERF 2025-01-20 16:50 73浏览
  • 高速先生成员--黄刚这不马上就要过年了嘛,高速先生就不打算给大家上难度了,整一篇简单但很实用的文章给大伙瞧瞧好了。相信这个标题一出来,尤其对于PCB设计工程师来说,心就立马凉了半截。他们辛辛苦苦进行PCB的过孔设计,高速先生居然说设计多大的过孔他们不关心!另外估计这时候就跳出很多“挑刺”的粉丝了哈,因为翻看很多以往的文章,高速先生都表达了过孔孔径对高速性能的影响是很大的哦!咋滴,今天居然说孔径不关心了?别,别急哈,听高速先生在这篇文章中娓娓道来。首先还是要对各位设计工程师的设计表示肯定,毕竟像我
    一博科技 2025-01-21 16:17 101浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦