一、学生个人情况介绍
25 届校招深信服技术岗一面面经|基础为王,附核心考点 + 详细回答思路 收藏 1 浏览 20042026-01-14 14:04:44 25 届校招深信服技术岗一面面经|基础为王,附核心考点 + 详细回答思路 收藏 1 浏览 20042026-01-14 14:04:44 25 届校招深信服技术岗一面面经|基础为王,附核心考点 + 详细回答思路 收藏 1 浏览 20042026-01-14 14:04:44 收藏 1 浏览 2004 收藏 1 浏览 2004 2026-01-14 14:04:44 本次分享一位 25 届应届生的深信服技术岗一面面经,面试整体难度偏基础,核心考察计算机核心基础与算法能力,希望能为同届校招同学提供参考。 一、学生个人情况介绍 本次分享的面经来自25 届应届毕业生,应聘深信服校招技术岗,本次为一面环节。该同学反馈面试体验良好,无超纲冷门考点,考察重点集中在C++ 编程语言、计算机网络、操作系统、SQL 基础 及经典手撕算法题,是典型的技术岗基础能力验证型面试。 二、面试企业和部门介绍 1. 企业介绍 深信服科技股份有限公司是国内头部的网络安全、云计算与 IT 基础设施解决方案提供商,业务覆盖政企、金融、教育、医疗等多个领域。校招技术岗招聘中,深信服高度重视候选人的计算机基础功底(网络、操作系统)、编程语言实战能力(以 C/C++ 为主)和算法思维,核心考察 “基础是否扎实” 而非 “冷门知识储备”。 2. 面试部门 本次面试为深信服通用技术岗一面,未明确细分具体业务部门,所有问题均围绕通用技术能力展开,无针对性的业务场景问题,聚焦基础能力验证。 三、面试核心内容与回答思路 面试内容分为五大模块,以下为每个问题的提问方向、详细回答思路及核心要点: 模块一:C++(核心编程语言考察) C++ 是本次面试的重点考察方向,问题均为技术岗高频基础考点,注重 “理解原理 + 能落地解释”。 问题 1:介绍 C++ 面向对象的三大特性 回答思路:先总述三大特性名称,再分别拆解每个特性的 “定义 + 核心价值 + 通俗示例”,让回答有层次、不空洞。 核心回答: C++ 面向对象的三大核心特性是继承、封装、多态,三者共同支撑 “代码复用、抽象化、逻辑灵活” 的编程思想: 继承:让子类获取父类的属性和方法,无需重复编写原有代码,同时可扩展新功能(如 “动物” 父类定义通用行为,“猫 / 狗” 子类继承后扩展 “叫” 的具体逻辑); 封装:将事物的属性和方法抽象为类,通过public/private/protected控制访问权限,对不可信的外部隐藏核心数据(如类的私有成员仅能被内部方法修改,避免外部误操作); 多态:同一消息发送给不同对象,执行不同逻辑 —— 编译时多态通过函数重载实现,运行时多态通过虚函数 / 纯虚函数实现(如父类指针指向子类对象,调用同一方法时执行子类逻辑)。 问题 2:C++ 11 有哪些新特性? 回答思路:优先列举 “高频实用” 的新特性,每个特性说明 “解决的问题 + 简单使用示例”,避免仅罗列名词。 核心回答: C++11 是 C++ 的里程碑版本,新增特性大幅提升开发效率,核心常用的有: nullptr:替代原有NULL(NULL本质是 0,易引发指针 / 整数类型混淆),专门表示空指针,类型更安全; 类型推导关键字:auto让编译器自动推导变量类型(如auto i = 10;推导为int),decltype推导表达式类型,减少复杂类型的冗余书写; 基于范围的 for 循环:简化容器遍历,如for(auto& i : res){}可直接遍历数组 / 容器,无需手动控制下标; Lambda 表达式:支持定义匿名函数,适用于临时简单逻辑(如容器排序时直接写排序规则); 右值引用与 move 语义:解决临时对象的拷贝效率问题,通过std::move实现资源转移,减少内存拷贝; 其他:类 / 结构体初始化列表(struct A{int a;}; A a{10};)、std::forward_list(单向链表,节省内存)等。 问题 3:hashtable 中解决冲突有哪些方法? 回答思路:先说明哈希冲突的本质(不同 key 映射到同一地址),再分点介绍每种方法的 “核心逻辑 + 优缺点”,突出工业界常用方案。 核心回答: 哈希冲突是 “不同 key 经哈希函数计算后得到同一数组下标”,常见解决方法有 4 种: 线性探测:冲突时向后依次找空位(表尾则回到表头),实现简单但易出现 “连续聚集”,降低查找效率; 开链法(拉链法):每个哈希位置维护一个链表,冲突的 key 插入对应链表,无聚集问题,是工业界主流方案(如 C++ unordered_map底层实现); 再散列:冲突时用另一哈希函数重新计算地址,直到找到空位,避免聚集但增加哈希计算开销; 二次探测:冲突时按平方步长(1²、2²、3²…)找空位,相比线性探测减少聚集,若步长为随机数则为伪随机探测。 问题 4:区分int *p[10]和int (*p)[10](指针数组 vs 数组指针) 回答思路:结合 “运算符优先级” 拆解语法,明确 “核心是数组” 还是 “核心是指针”,配合通俗解释。 核心回答: 区分的关键是[]优先级高于*,核心看 “本质是数组还是指针”: int *p[10]:指针数组 —— 先构成数组p[10],数组的每个元素是int*类型(指向 int 的指针),核心是 “数组”; int (*p)[10]:数组指针 ——()提升*优先级,先构成指针p,该指针指向 “包含 10 个 int 元素的数组”,核心是 “指针”。 模块二:操作系统 操作系统考察聚焦 “内存管理” 和 “数据存储”,均为技术岗必考点,注重 “对比记忆 + 原理理解”。 问题 5:堆和栈的区别 回答思路:从 “管理方式、内存机制、空间大小、碎片、生长方向、分配方式、效率”7 个维度对比,结合通俗解释辅助理解。 核心回答(表格梳理): 对比维度 堆 栈 管理方式 程序员手动控制(new/delete),易内存泄漏 编译器自动管理,出作用域自动释放 内存管理机制 基于空闲链表分配,找首个足够大的内存块 连续内存,剩余空间足够则分配,否则栈溢出 空间大小 不连续,受虚拟内存限制(32 位系统理论 4G),空间大且灵活 连续,大小固定(Windows 默认 2M),空间小 碎片问题 频繁new/delete易产生内存碎片,降低效率 先进后出,进出一一对应,无碎片 生长方向 向上(高地址方向) 向下(低地址方向) 分配方式 仅动态分配 静态分配(局部变量)+ 动态分配(alloca函数),均自动释放 分配效率 函数库实现,机制复杂,效率低 系统底层支持(专用寄存器 / 指令),效率高 问题 6:大小端存储是什么意思?如何区分? 回答思路:先定义大小端,结合数值示例说明存储方式,再给出两种可运行的代码判断方法,解释核心原理。 核心回答: 1. 大小端定义 大小端是多字节数据的内存存储顺序,核心区别: 大端存储:高字节存低地址(符合人类阅读习惯,如 0x12345678,低地址存 0x12); 小端存储:低字节存低地址(主流操作系统采用,如 0x12345678,低地址存 0x78); 注:网络传输用大端,Socket 编程需将主机小端转为网络大端。 2. 代码判断方法 方法一:强制类型转换(利用 int 转 char 仅保留低地址字节) cpp 运行 #include using namespace std; int main() { int a = 0x1234; char c = (char)a; // 仅保留低地址字节 if (c == 0x12) cout 4->2 ListNode* head = new ListNode(1); head->next = new ListNode(2); head->next->next = new ListNode(3); head->next->next->next = new ListNode(4); head->next->next->next->next = head->next; // 环指向2 cout next = new ListNode(2); head->next->next = new ListNode(3); head->next->next->next = new ListNode(4); head->next->next->next->next = head->next; // 环指向2 cout
二、面试企业和部门介绍
1. 企业介绍
深信服科技股份有限公司是国内头部的网络安全、云计算与 IT 基础设施解决方案提供商,业务覆盖政企、金融、教育、医疗等多个领域。校招技术岗招聘中,深信服高度重视候选人的计算机基础功底(网络、操作系统)、编程语言实战能力(以 C/C++ 为主)和算法思维,核心考察 “基础是否扎实” 而非 “冷门知识储备”。
2. 面试部门
本次面试为深信服通用技术岗一面,未明确细分具体业务部门,所有问题均围绕通用技术能力展开,无针对性的业务场景问题,聚焦基础能力验证。 通用技术岗
三、面试核心内容与回答思路
面试内容分为五大模块,以下为每个问题的提问方向、详细回答思路及核心要点:
模块一:C++(核心编程语言考察)
C++ 是本次面试的重点考察方向,问题均为技术岗高频基础考点,注重 “理解原理 + 能落地解释”。 问题 1:介绍 C++ 面向对象的三大特性 回答思路:先总述三大特性名称,再分别拆解每个特性的 “定义 + 核心价值 + 通俗示例”,让回答有层次、不空洞。 核心回答: C++ 面向对象的三大核心特性是继承、封装、多态,三者共同支撑 “代码复用、抽象化、逻辑灵活” 的编程思想: 回答思路 核心回答 继承:让子类获取父类的属性和方法,无需重复编写原有代码,同时可扩展新功能(如 “动物” 父类定义通用行为,“猫 / 狗” 子类继承后扩展 “叫” 的具体逻辑); 封装:将事物的属性和方法抽象为类,通过public/private/protected控制访问权限,对不可信的外部隐藏核心数据(如类的私有成员仅能被内部方法修改,避免外部误操作); 多态:同一消息发送给不同对象,执行不同逻辑 —— 编译时多态通过函数重载实现,运行时多态通过虚函数 / 纯虚函数实现(如父类指针指向子类对象,调用同一方法时执行子类逻辑)。 继承:让子类获取父类的属性和方法,无需重复编写原有代码,同时可扩展新功能(如 “动物” 父类定义通用行为,“猫 / 狗” 子类继承后扩展 “叫” 的具体逻辑); 封装:将事物的属性和方法抽象为类,通过public/private/protected控制访问权限,对不可信的外部隐藏核心数据(如类的私有成员仅能被内部方法修改,避免外部误操作); public/private/protected 多态:同一消息发送给不同对象,执行不同逻辑 —— 编译时多态通过函数重载实现,运行时多态通过虚函数 / 纯虚函数实现(如父类指针指向子类对象,调用同一方法时执行子类逻辑)。 问题 2:C++ 11 有哪些新特性? 回答思路:优先列举 “高频实用” 的新特性,每个特性说明 “解决的问题 + 简单使用示例”,避免仅罗列名词。 核心回答: C++11 是 C++ 的里程碑版本,新增特性大幅提升开发效率,核心常用的有: 回答思路 核心回答 nullptr:替代原有NULL(NULL本质是 0,易引发指针 / 整数类型混淆),专门表示空指针,类型更安全; 类型推导关键字:auto让编译器自动推导变量类型(如auto i = 10;推导为int),decltype推导表达式类型,减少复杂类型的冗余书写; 基于范围的 for 循环:简化容器遍历,如for(auto& i : res){}可直接遍历数组 / 容器,无需手动控制下标; Lambda 表达式:支持定义匿名函数,适用于临时简单逻辑(如容器排序时直接写排序规则); 右值引用与 move 语义:解决临时对象的拷贝效率问题,通过std::move实现资源转移,减少内存拷贝; 其他:类 / 结构体初始化列表(struct A{int a;}; A a{10};)、std::forward_list(单向链表,节省内存)等。 nullptr:替代原有NULL(NULL本质是 0,易引发指针 / 整数类型混淆),专门表示空指针,类型更安全; nullptr NULL NULL 类型推导关键字:auto让编译器自动推导变量类型(如auto i = 10;推导为int),decltype推导表达式类型,减少复杂类型的冗余书写; auto auto i = 10; int decltype 基于范围的 for 循环:简化容器遍历,如for(auto& i : res){}可直接遍历数组 / 容器,无需手动控制下标; for(auto& i : res){} Lambda 表达式:支持定义匿名函数,适用于临时简单逻辑(如容器排序时直接写排序规则); 右值引用与 move 语义:解决临时对象的拷贝效率问题,通过std::move实现资源转移,减少内存拷贝; std::move 其他:类 / 结构体初始化列表(struct A{int a;}; A a{10};)、std::forward_list(单向链表,节省内存)等。 struct A{int a;}; A a{10}; std::forward_list 问题 3:hashtable 中解决冲突有哪些方法? 回答思路:先说明哈希冲突的本质(不同 key 映射到同一地址),再分点介绍每种方法的 “核心逻辑 + 优缺点”,突出工业界常用方案。 核心回答: 哈希冲突是 “不同 key 经哈希函数计算后得到同一数组下标”,常见解决方法有 4 种: 回答思路 核心回答 线性探测:冲突时向后依次找空位(表尾则回到表头),实现简单但易出现 “连续聚集”,降低查找效率; 开链法(拉链法):每个哈希位置维护一个链表,冲突的 key 插入对应链表,无聚集问题,是工业界主流方案(如 C++ unordered_map底层实现); 再散列:冲突时用另一哈希函数重新计算地址,直到找到空位,避免聚集但增加哈希计算开销; 二次探测:冲突时按平方步长(1²、2²、3²…)找空位,相比线性探测减少聚集,若步长为随机数则为伪随机探测。 线性探测:冲突时向后依次找空位(表尾则回到表头),实现简单但易出现 “连续聚集”,降低查找效率; 开链法(拉链法):每个哈希位置维护一个链表,冲突的 key 插入对应链表,无聚集问题,是工业界主流方案(如 C++ unordered_map底层实现); unordered_map 再散列:冲突时用另一哈希函数重新计算地址,直到找到空位,避免聚集但增加哈希计算开销; 二次探测:冲突时按平方步长(1²、2²、3²…)找空位,相比线性探测减少聚集,若步长为随机数则为伪随机探测。 问题 4:区分int *p[10]和int (*p)[10](指针数组 vs 数组指针) int *p[10] int (*p)[10] 回答思路:结合 “运算符优先级” 拆解语法,明确 “核心是数组” 还是 “核心是指针”,配合通俗解释。 核心回答: 区分的关键是[]优先级高于*,核心看 “本质是数组还是指针”: 回答思路 核心回答 [] * int *p[10]:指针数组 —— 先构成数组p[10],数组的每个元素是int*类型(指向 int 的指针),核心是 “数组”; int (*p)[10]:数组指针 ——()提升*优先级,先构成指针p,该指针指向 “包含 10 个 int 元素的数组”,核心是 “指针”。 int *p[10]:指针数组 —— 先构成数组p[10],数组的每个元素是int*类型(指向 int 的指针),核心是 “数组”; int *p[10] p[10] int* int (*p)[10]:数组指针 ——()提升*优先级,先构成指针p,该指针指向 “包含 10 个 int 元素的数组”,核心是 “指针”。 int (*p)[10] () * p
模块二:操作系统
操作系统考察聚焦 “内存管理” 和 “数据存储”,均为技术岗必考点,注重 “对比记忆 + 原理理解”。 问题 5:堆和栈的区别 回答思路:从 “管理方式、内存机制、空间大小、碎片、生长方向、分配方式、效率”7 个维度对比,结合通俗解释辅助理解。 核心回答(表格梳理): 回答思路 核心回答(表格梳理) 对比维度 堆 栈 管理方式 程序员手动控制(new/delete),易内存泄漏 编译器自动管理,出作用域自动释放 内存管理机制 基于空闲链表分配,找首个足够大的内存块 连续内存,剩余空间足够则分配,否则栈溢出 空间大小 不连续,受虚拟内存限制(32 位系统理论 4G),空间大且灵活 连续,大小固定(Windows 默认 2M),空间小 碎片问题 频繁new/delete易产生内存碎片,降低效率 先进后出,进出一一对应,无碎片 生长方向 向上(高地址方向) 向下(低地址方向) 分配方式 仅动态分配 静态分配(局部变量)+ 动态分配(alloca函数),均自动释放 分配效率 函数库实现,机制复杂,效率低 系统底层支持(专用寄存器 / 指令),效率高 对比维度 堆 栈 管理方式 程序员手动控制(new/delete),易内存泄漏 编译器自动管理,出作用域自动释放 内存管理机制 基于空闲链表分配,找首个足够大的内存块 连续内存,剩余空间足够则分配,否则栈溢出 空间大小 不连续,受虚拟内存限制(32 位系统理论 4G),空间大且灵活 连续,大小固定(Windows 默认 2M),空间小 碎片问题 频繁new/delete易产生内存碎片,降低效率 先进后出,进出一一对应,无碎片 生长方向 向上(高地址方向) 向下(低地址方向) 分配方式 仅动态分配 静态分配(局部变量)+ 动态分配(alloca函数),均自动释放 分配效率 函数库实现,机制复杂,效率低 系统底层支持(专用寄存器 / 指令),效率高 对比维度 堆 栈 管理方式 程序员手动控制(new/delete),易内存泄漏 编译器自动管理,出作用域自动释放 内存管理机制 基于空闲链表分配,找首个足够大的内存块 连续内存,剩余空间足够则分配,否则栈溢出 空间大小 不连续,受虚拟内存限制(32 位系统理论 4G),空间大且灵活 连续,大小固定(Windows 默认 2M),空间小 碎片问题 频繁new/delete易产生内存碎片,降低效率 先进后出,进出一一对应,无碎片 生长方向 向上(高地址方向) 向下(低地址方向) 分配方式 仅动态分配 静态分配(局部变量)+ 动态分配(alloca函数),均自动释放 分配效率 函数库实现,机制复杂,效率低 系统底层支持(专用寄存器 / 指令),效率高 对比维度 堆 栈 对比维度 堆 栈 对比维度 堆 栈 管理方式 程序员手动控制(new/delete),易内存泄漏 编译器自动管理,出作用域自动释放 内存管理机制 基于空闲链表分配,找首个足够大的内存块 连续内存,剩余空间足够则分配,否则栈溢出 空间大小 不连续,受虚拟内存限制(32 位系统理论 4G),空间大且灵活 连续,大小固定(Windows 默认 2M),空间小 碎片问题 频繁new/delete易产生内存碎片,降低效率 先进后出,进出一一对应,无碎片 生长方向 向上(高地址方向) 向下(低地址方向) 分配方式 仅动态分配 静态分配(局部变量)+ 动态分配(alloca函数),均自动释放 分配效率 函数库实现,机制复杂,效率低 系统底层支持(专用寄存器 / 指令),效率高 管理方式 程序员手动控制(new/delete),易内存泄漏 编译器自动管理,出作用域自动释放 管理方式 程序员手动控制(new/delete),易内存泄漏 new/delete 编译器自动管理,出作用域自动释放 内存管理机制 基于空闲链表分配,找首个足够大的内存块 连续内存,剩余空间足够则分配,否则栈溢出 内存管理机制 基于空闲链表分配,找首个足够大的内存块 连续内存,剩余空间足够则分配,否则栈溢出 空间大小 不连续,受虚拟内存限制(32 位系统理论 4G),空间大且灵活 连续,大小固定(Windows 默认 2M),空间小 空间大小 不连续,受虚拟内存限制(32 位系统理论 4G),空间大且灵活 连续,大小固定(Windows 默认 2M),空间小 碎片问题 频繁new/delete易产生内存碎片,降低效率 先进后出,进出一一对应,无碎片 碎片问题 频繁new/delete易产生内存碎片,降低效率 new/delete 先进后出,进出一一对应,无碎片 生长方向 向上(高地址方向) 向下(低地址方向) 生长方向 向上(高地址方向) 向下(低地址方向) 分配方式 仅动态分配 静态分配(局部变量)+ 动态分配(alloca函数),均自动释放 分配方式 仅动态分配 静态分配(局部变量)+ 动态分配(alloca函数),均自动释放 alloca 分配效率 函数库实现,机制复杂,效率低 系统底层支持(专用寄存器 / 指令),效率高 分配效率 函数库实现,机制复杂,效率低 系统底层支持(专用寄存器 / 指令),效率高 问题 6:大小端存储是什么意思?如何区分? 回答思路:先定义大小端,结合数值示例说明存储方式,再给出两种可运行的代码判断方法,解释核心原理。 核心回答: 回答思路 核心回答 1. 大小端定义 大小端是多字节数据的内存存储顺序,核心区别: 大端存储:高字节存低地址(符合人类阅读习惯,如 0x12345678,低地址存 0x12); 小端存储:低字节存低地址(主流操作系统采用,如 0x12345678,低地址存 0x78); 注:网络传输用大端,Socket 编程需将主机小端转为网络大端。 大端存储:高字节存低地址(符合人类阅读习惯,如 0x12345678,低地址存 0x12); 小端存储:低字节存低地址(主流操作系统采用,如 0x12345678,低地址存 0x78); 注:网络传输用大端,Socket 编程需将主机小端转为网络大端。 注:网络传输用大端,Socket 编程需将主机小端转为网络大端。 2. 代码判断方法 方法一:强制类型转换(利用 int 转 char 仅保留低地址字节) 方法一:强制类型转换(利用 int 转 char 仅保留低地址字节) cpp 运行 #include using namespace std; int main() { int a = 0x1234; char c = (char)a; // 仅保留低地址字节 if (c == 0x12) cout
模块二:计算机网络
网络考察聚焦 “TCP 可靠性” 和 “会话管理”,均为校招高频考点,注重 “机制理解 + 对比分析”。 问题 7:TCP 是如何保证可靠传输的? 回答思路:从 “确认重传、数据校验、分片排序、流量控制、拥塞控制”5 个维度展开,每个机制说明 “作用 + 实现方式”,对比 UDP 突出 TCP 的可靠性。 核心回答: TCP 通过 5 大核心机制保证可靠传输: 回答思路 核心回答 确认与重传:接收方收到报文返回 ACK 确认,发送方超时未收到则重传; 数据校验:TCP 报文头含校验和,接收方验证报文是否损坏,损坏则丢弃并触发重传; 分片与排序:按 MTU 合理分片,接收方缓存未按序分片,排序后交给应用层(UDP 分片丢失则丢弃整个数据报); 流量控制:基于滑动窗口,接收方通过窗口大小告知发送方接收能力,避免接收方处理不及时丢包; 拥塞控制:基于拥塞窗口,通过慢启动、拥塞避免等算法,减少网络拥塞时的发送速率。 确认与重传:接收方收到报文返回 ACK 确认,发送方超时未收到则重传; 数据校验:TCP 报文头含校验和,接收方验证报文是否损坏,损坏则丢弃并触发重传; 分片与排序:按 MTU 合理分片,接收方缓存未按序分片,排序后交给应用层(UDP 分片丢失则丢弃整个数据报); 流量控制:基于滑动窗口,接收方通过窗口大小告知发送方接收能力,避免接收方处理不及时丢包; 拥塞控制:基于拥塞窗口,通过慢启动、拥塞避免等算法,减少网络拥塞时的发送速率。 问题 8:Cookies 和 Session 分别存放在哪里? 回答思路:先明确存储位置,再补充 “安全性 + 数据大小” 等延伸点,让回答更完整。 核心回答: Cookie 和 Session 是维持会话的核心机制,核心区别在存储位置: 回答思路 核心回答 Cookie:存储在客户端(浏览器),是服务器发送的小型文本文件,大小受限(约 4KB),安全性低(易被篡改),可设置过期时间; Session:存储在服务端(内存 / 数据库 / 缓存),服务器生成唯一 SessionID 并通过 Cookie 传递给客户端,数据更安全、无大小限制,适用于存储敏感信息(如登录状态)。 Cookie:存储在客户端(浏览器),是服务器发送的小型文本文件,大小受限(约 4KB),安全性低(易被篡改),可设置过期时间; 客户端(浏览器) Session:存储在服务端(内存 / 数据库 / 缓存),服务器生成唯一 SessionID 并通过 Cookie 传递给客户端,数据更安全、无大小限制,适用于存储敏感信息(如登录状态)。 服务端(内存 / 数据库 / 缓存)
模块三:SQL
考察分组统计的基础语法,聚焦GROUP BY的核心使用,注重 “需求拆解 + 语法正确性”。 GROUP BY 问题 9:班级成绩表(grades),区分 sex 为 male 和 female,如何写 SQL? 回答思路:先明确需求(按性别分组,统计人数 + 平均分),再给出 SQL 语句,解释核心关键字的作用。 核心回答: 需求是按性别(male/female)分组,统计每组的学生数量和平均成绩,SQL 语句及解释如下: 回答思路 核心回答 sql SELECT sex, -- 分组维度:性别 COUNT(*) AS total_students, -- 统计每组学生数 AVG(score) AS average_score -- 计算每组平均分 FROM grades WHERE sex IN ('male', 'female') -- 筛选有效性别(可选) GROUP BY sex; -- 按性别分组 sql SELECT sex, -- 分组维度:性别 COUNT(*) AS total_students, -- 统计每组学生数 AVG(score) AS average_score -- 计算每组平均分 FROM grades WHERE sex IN ('male', 'female') -- 筛选有效性别(可选) GROUP BY sex; -- 按性别分组 sql sql sql sql SELECT sex, -- 分组维度:性别 COUNT(*) AS total_students, -- 统计每组学生数 AVG(score) AS average_score -- 计算每组平均分 FROM grades WHERE sex IN ('male', 'female') -- 筛选有效性别(可选) GROUP BY sex; -- 按性别分组 SELECT sex, -- 分组维度:性别 COUNT(*) AS total_students, -- 统计每组学生数 AVG(score) AS average_score -- 计算每组平均分 FROM grades WHERE sex IN ('male', 'female') -- 筛选有效性别(可选) GROUP BY sex; -- 按性别分组 SELECT sex, -- 分组维度:性别 COUNT(*) AS total_students, -- 统计每组学生数 AVG(score) AS average_score -- 计算每组平均分 FROM grades WHERE sex IN ('male', 'female') -- 筛选有效性别(可选) GROUP BY sex; -- 按性别分组 SELECT , -- 分组维度:性别 COUNT ( * ) AS , -- 统计每组学生数 AVG ( ) AS -- 计算每组平均分 FROM WHERE IN ( 'male' , 'female' ) -- 筛选有效性别(可选) GROUP BY ; -- 按性别分组
模块四:手撕算法(现场编码)
算法题考察经典题型,注重 “代码逻辑正确 + 边界条件处理”,以下为完整可运行代码及思路: 算法题 1:手写快速排序 核心思路:分治思想 —— 选基准值→分区(小于基准放左,大于放右)→递归排序左右子数组,注意边界条件(low >= high时终止递归)。 核心思路 low >= high cpp 运行 #include #include using namespace std; // 分区函数:返回基准值的正确下标 int partition(vector& nums, int low, int high) { int pivot = nums[high]; // 选最右元素为基准 int i = low - 1; // 小于基准的区域边界 for (int j = low; j < high; j++) { if (nums[j] 1才排序 int pi = partition(nums, low, high); quickSort(nums, low, pi - 1); // 排序左子数组 quickSort(nums, pi + 1, high); // 排序右子数组 } } // 测试示例 int main() { vector nums = {3,1,4,1,5,9,2,6}; quickSort(nums, 0, nums.size()-1); for (int num : nums) cout 4->2 ListNode* head = new ListNode(1); head->next = new ListNode(2); head->next->next = new ListNode(3); head->next->next->next = new ListNode(4); head->next->next->next->next = head->next; // 环指向2 cout next; // 快指针:走2步 while (slow != fast) { if (fast == NULL || fast->next == NULL) return false; // 快指针到尾,无环 slow = slow->next; fast = fast->next->next; } return true; // 相遇,有环 } // 测试示例 int main() { // 构造有环链表:1->2->3->4->2 ListNode* head = new ListNode(1); head->next = new ListNode(2); head->next->next = new ListNode(3); head->next->next->next = new ListNode(4); head->next->next->next->next = head->next; // 环指向2 cout next; // 快指针:走2步 while (slow != fast) { if (fast == NULL || fast->next == NULL) return false; // 快指针到尾,无环 slow = slow->next; fast = fast->next->next; } return true; // 相遇,有环 } // 测试示例 int main() { // 构造有环链表:1->2->3->4->2 ListNode* head = new ListNode(1); head->next = new ListNode(2); head->next->next = new ListNode(3); head->next->next->next = new ListNode(4); head->next->next->next->next = head->next; // 环指向2 cout next; // 快指针:走2步 while (slow != fast) { if (fast == NULL || fast->next == NULL) return false; // 快指针到尾,无环 slow = slow->next; fast = fast->next->next; } return true; // 相遇,有环 } // 测试示例 int main() { // 构造有环链表:1->2->3->4->2 ListNode* head = new ListNode(1); head->next = new ListNode(2); head->next->next = new ListNode(3); head->next->next->next = new ListNode(4); head->next->next->next->next = head->next; // 环指向2 cout next; // 快指针:走2步 while (slow != fast) { if (fast == NULL || fast->next == NULL) return false; // 快指针到尾,无环 slow = slow->next; fast = fast->next->next; } return true; // 相遇,有环 } // 测试示例 int main() { // 构造有环链表:1->2->3->4->2 ListNode* head = new ListNode(1); head->next = new ListNode(2); head->next->next = new ListNode(3); head->next->next->next = new ListNode(4); head->next->next->next->next = head->next; // 环指向2 cout ; // 快指针:走2步 while ( != ) { if ( == NULL || -> == NULL ) return false ; // 快指针到尾,无环 = -> ; = -> -> ; } return true ; // 相遇,有环 } // 测试示例 int main ( ) { // 构造有环链表:1->2->3->4->2 * = new ListNode ( 1 ) ; -> = new ListNode ( 2 ) ; -> -> = new ListNode ( 3 ) ; -> -> -> = new ListNode ( 4 ) ; -> -> -> -> = -> ; // 环指向2
四、总结
关键点回顾
面试难度:深信服技术岗一面以基础为主,无偏题怪题,核心考察 C++、操作系统、计算机网络三大核心学科,SQL 和算法为常规经典题; 备考重点:编程语言聚焦 C++ 面向对象、指针、C++11 特性,基础学科注重 “原理理解” 而非死记硬背,算法掌握快排、链表判环等经典题; 回答技巧:回答问题时先总述核心要点,再分点拆解,结合 “通俗示例 / 应用场景” 说明,避免仅罗列知识点。 面试难度:深信服技术岗一面以基础为主,无偏题怪题,核心考察 C++、操作系统、计算机网络三大核心学科,SQL 和算法为常规经典题; 基础为主 备考重点:编程语言聚焦 C++ 面向对象、指针、C++11 特性,基础学科注重 “原理理解” 而非死记硬背,算法掌握快排、链表判环等经典题; 回答技巧:回答问题时先总述核心要点,再分点拆解,结合 “通俗示例 / 应用场景” 说明,避免仅罗列知识点。 收藏文章 收藏文章
