结束
一次完整的面试流程就是这样啦,小编综合了腾讯的面试题做了一份前端面试题PDF文档,里面有面试题的详细解析,分享给小伙伴们,有没有需要的小伙伴们都去领取!
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
(1)
首先我们得了解,什么是强连通?
如果在一个有向图顶点子集内,任取两个点 u 和 v ,都能找到一条路径从 u 到 v ,则称该子集为强连通
(2)
其次我们得了解,什么是强连通分量?
如果我们在一个强连通的顶点集合内,加入其他其他任意顶点集合后,它都会变得不再是强连通的,则称该顶点集合为强连通分量
(3)
最后我们得了解,什么是强连通分量分解?
任意有向图都可被分解成若干个不相交的强连通分量(这个不相交,指不同分量中顶点都是不同的),这就是强连通分量分解
注意:我们一般是对有向有环图进行强连通分量,因为有向无环图中,没有强连通分量,无向图中,所有顶点集是一个强连通分量,这种分解没有意义
(4)
那我们怎么进行强连通分量分解?
我们首先进行一次 dfs ,选取任意顶点作为起点,遍历所有尚未访问过的顶点,并在回溯前给顶点标号(后序遍历),对剩余未访问过的顶点,不断重复上述过程
这次的标号主要是为了使越接近图的尾部,顶点的标号越小,为后续操作做铺垫
怎么标号?
我们可以建立一个 vector 容器,这样我们将越接近图的尾部的,越先放入
为什么可以从任何顶点开始?
因为我们是把尾部最先放入。不管我们从哪个点开始遍历,都能遍历到当前剩余顶点集当中,最接近尾部的点,所以不管我们从哪里遍历,都能将该点及该点后面的所有点正确放入。
例如我们按 1 2 3 号顶点的顺序开始遍历,那么我们放入的点,就是圈起来的部分。
很容易看出不管从哪个点开始,都能正确完成操作
为什么需要后序遍历?(即先向下递归,回溯时在放入 vector)
因为我们是越接近图的尾部,越先放入。
如果是前序遍历就相当于越接近头部越先放入,这样会出错,因为我们从任意顶点开始遍历,比如我们按 1 2 3 的顺序进行遍历,这样我们先放的相当于是 顶点1 ,而顶点 1 并非头部,这样就会出错
我们再进行一次 dfs ,先将所有边反向,然后以标号最大的顶点为起点进行 dfs ,每次 dfs 所遍历的顶点集合就构成了一个强连通分量,拿个数组保存以下各个点属于哪个强连通分量即可
反向,其实就是记录边的时候多记录一条反向边
从标号最大的开始遍历,其实就是将 vector 从后向前遍历一次
这个的思路是这样的:
**因为我们是按从头部到尾部遍历,所以我们正在遍历的只有两种情况
例:如果我们遍历到 顶点1 ,此时没有遍历过的可能是 ”旁边“ 的,或者 “后面” 的
(阴影的相当于已经遍历过)
对于“旁边”:由于上游的点已经遍历过,所以旁边的点递归不到,所以不用考虑
对于“后面”:假设 顶点v 在 顶点u 的“后面”,因为在“后面”,所以有条 u 到 v 的路径,如果把边反向后,仍然 顶点u 有路径到达 顶点v ,相当于在正向图中有一条 v 到 u 的路径,证明 u 到 v 连通**
代码如下:
#include
#include <stdio.h>
#include
#include <string.h>
using namespace std;
vector data[10005];
vector rdata[10005];
vector flag;
int used[10005];
int kind[10005];
void add_edge(int i, int j)
{
data[i].push_back(j);
rdata[j].push_back(i);
刷面试题
刷题的重要性,不用多说。对于应届生或工作年限不长的人来说,刷面试题一方面能够尽可能地快速自己对某个技术点的理解,另一方面在面试时,有一定几率被问到相同或相似题,另外或多或少也能够为自己面试增加一些自信心,可见适当的刷题是很有必要的。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
-
前端字节跳动真题解析
-
【269页】前端大厂面试题宝典
最后平时要进行自我分析与评价,做好职业规划,不断摸索,提高自己的编程能力和抽象思维能力。大厂面试远没有我们想的那么困难,摆好心态,做好准备,你也可以的。