type
status
date
slug
summary
tags
category
icon
password
状态
专注质量
预计(分钟)
开始时间
结束时间
文章来源说明

🤔 客户端开发笔试常见知识汇总

目录

选择题和简答题高频题目

已知二叉树前序和中序,求后序序列

首先知道二叉树的三种序列分别代表什么含义:
  1. 前序:根左右
  1. 中序:左根右
  1. 后序:左右根
因此,如果已知前序,那个第一个节点一定是根节点,然后根据中序序列,就能切出左子树和右子树,一步步递归得到整个序列。这种题目只要花费一定时间,都能推出来,并且最后可以反过来验算,了解方法即可达到100%正确率!

入栈顺序ABCDEFG,则出栈顺序不可能是___

这种序列就看哪一个元素是第一个不按顺序出栈的。
比如ABCDEFG,看似出栈和入栈顺序一样,但是是合理的,因为进去之后马上出栈就可以!
但如果是ADxxxxx,那么你就知道了,B在栈底,C在B上面,此时便会出现出栈序列的矛盾。

排序算法

快速排序

最高频的考点,可以从以下多个方面考察:
  1. 基础概念
时间复杂度?是否稳定?
  1. 具体流程
如果选择最后一个元素作为基准元素,那么排序完成一共需要几次比较?
  1. 手撸实现
理论上只要知道第三条,1、2条的考点也不会被难倒。快排的算法实现就两条,递归和左右指针。一般都是以第一个元素或者最后一个元素为基准,相当于挖了个坑,然后从另一侧找到第一个比基准元素大(或者小)的元素,交换;那么另一侧原来的位置就又多出来个坑,从反面找到第一个比基准元素小(或者大)的元素,交换,重复这个过程知道left==right。此时就能达到左侧都比基准元素大,右侧均比基准元素小的状态了,最后迭代排列两个左右区间。

冒泡排序

从后往前遍历的话,每一轮都能把最大(或者最小)的元素不断交换到最前面。
实现思路非常简单,并且算法稳定。

选择排序

每一轮找到一个最值,放在序列最前面。
是不稳定。

插入排序

数组分为两段,一段为已经排序的,另一段为未排序的。
每次选择未排序序列中的第一个,找到其在有序序列中的位置。
是一种稳定算法

归并排序

不断二分数组,分到不能在分之后,反向递归,合并成有序序列。
比如(54321)需要排成从小到大。
第一次分成543,21
第二次分成54 3 21
第三次分成5 4 3 2 1
第一次归并为45 3 12
第二次归并为345 12
第三次归并为12345
简单的问题,可以问归并算法是否稳定(稳定),时间复杂度。
复杂一点,需要手写代码,但总体来说不难。

堆排序

堆可以用数组实现,因为可以将数组视为一个完全二叉树,那么根节点和子节点在数组中的索引是有规律的,比如根节点数组下标为i,左叶子就是2i,右叶子是2i+1。(如果有的话)
堆排序的流程如下:
  1. 建堆,从最后一个非叶子节点开始,与其孩子交换,将较大(小)的元素往上调整
  1. 此时堆顶元素就是最大值,将其与最后一个元素交换,将剩下的堆元素重新调整为堆
  1. 反复这个过程,知道堆中只剩下一个元素
这是一种不稳定的算法,且时间复杂度为nlogn级别。

希尔排序

没有研究过具体实现,只知道平均复杂度为n的1.3次幂,最坏为n平方,最好为n。
是一种不稳定的排序算法。

最后三种

计数排序、桶排序和箱排序,属于低频考点

结构体所占内存

📝算法题

C++算法题中常用的api整理(转载知乎用户“好吃的无锡油面筋”)

std::vector<T>
  • push_back(const T& value): 添加元素至末尾
  • pop_back(): 移除末尾元素
  • size(): 获取元素数量
  • empty(): 检查容器是否为空
  • clear(): 清空容器
  • begin(), end(): 获取迭代器
std::list<T>
  • push_back(const T& value), push_front(const T& value): 添加元素
  • pop_back(), pop_front(): 移除元素
  • size(), empty(), clear(): 同std::vector
  • begin(), end(): 获取迭代器
std::set<T>
  • insert(const T& value): 插入元素
  • erase(const T& value): 删除元素
  • find(const T& value): 查找元素
  • size(), empty(), clear(), begin(), end(): 同std::vector
std::map<K, V>, std::unordered_map<K, V>
  • insert(std::make_pair(key, value)): 插入键值对
  • erase(const K& key): 根据键删除元素
  • find(const K& key): 查找键
  • size(), empty(), clear(), begin(), end(): 同std::vector
std::queue<T>
  • push(const T& value): 添加元素至末尾
  • pop(): 移除首元素
  • front(): 获取首元素
  • size(), empty(): 同std::vector
std::stack<T>
  • push(const T& value): 添加元素至顶部
  • pop(): 移除顶部元素
  • top(): 获取顶部元素
  • size(), empty(): 同std::vector
std::priority_queue<T>
  • push(const T& value): 插入元素
  • pop(): 移除顶部元素
  • top(): 获取顶部元素
  • size(), empty(): 同std::vector
♥️字符串相关:
getline
std::string line; std::getline( cin, line ); // 从标准输入读取一整行
stringstream
  • str(): 获取或设置流中的字符串内容
  • get(): 获取下一个字符
  • <<: 插入操作符,将数据插入到流中
  • >>: 提取操作符,从流中提取数据
  • clear(): 清除流的状态标志
  • peek(): 查看下一个字符
"1,234,567"去掉逗号,可以通过以下方法来实现:
字符串相关处理我一般可能会接收之后遍历一次字符串,去掉‘,’,这里的做法明显是一种更好的做法。
其它
构建数组
int arr[][]={0,1,0,-1,1,0,-1,0};
sort函数
可以定义一个返回值为bool的cmp函数作为比较器,在一些题目中很有用
stoi和stof函数
将字符串转为特定类型值

🤗自己积累可能会用上的知识

四叉树和八叉树

定义

一种树型数据结构,分别代表最多有几个子节点。

应用场景

对空间进行分割,方便检测互相之间的碰撞,或者其它需要两两检测的场景。

算法过程

以四叉树为例,其理解逻辑参考堆:
  1. 第一步是如何构建四叉树,四叉树一般会有一个maxDepth和一个capcity,前者即最深遍历深度,用于控制整体规模,后者用于限制每个树节点存储的孩子个数。在构建时,当超过capcity时,开始对当前空间进行四等分,查询当前节点在哪个区间并添加。如果当前节点处在交叉位置,则需要添加到父节点处,无视capcity的存在
  1. 第二步是应用,显然,当四叉树已经构建好后,假设当前需要求一个圆A的所有碰撞时,可以快速过滤无用的节点。其父节点以及所有兄弟节点即为它所能接触到的所有可能的节点!
  1. 另外就是插入和删除,插入跟构建时的步骤一样;删除时需要注意,可能会动态调整树的结构,达到优化目的。

思考

学习一个知识,如果没有深刻实践的话,很难能有深刻理解或者记忆。但复习时也要抓住根本目的,如果是为了找工作,未必面面俱到,对每个领域都有所了解就很好了。

图形学相关

渲染管线

应用阶段—几何阶段—光栅化阶段
顶点着色器出现在几何几段,片元着色器出现在光栅化阶段

参考文章

致谢:
💡
Written by Aryue,editted by Notion AI.
 
 
代码随想录-单调栈、图论、并查集代码随想录—动态规划
Aryue
Aryue
一个普通的干饭人🍚
公告
type
status
date
slug
summary
tags
category
icon
password
状态
专注质量
预计(分钟)
开始时间
结束时间
📧:578626935@qq.com