摘要: 树与图的DFS与BFS 树与图的DFS与BFS DFS BFS 首先,树是一种特殊结构的图,所以树与图的存储是相同的,而图又分为有向图与无向图,对无向图我们可以在两个点之间添加两条边。 有向图的存储方式主要有两种 稀疏图(点多边少)一般用邻接表存储 稠密图(点少边多)一般用邻接矩阵存储。 在邻接表的 阅读全文
posted @ 2022-12-09 22:07 S!no 阅读(107) 评论(0) 推荐(0)
摘要: 宽度优先搜索 BFS 宽度优先搜索 BFS 走迷宫 八数码 宽度优先搜索每次扩展当前结点的所有相邻结点,所以需要一个队列来维护要扩展的结点。由于宽度优先搜索每次都是把所有能到的下一步搜完,所以能够得到最短路径的解,所以一些不带权求最短路径的问题也可以直接用BFS解决。 注意,在扩展结点的某个下一结点 阅读全文
posted @ 2022-12-09 22:07 S!no 阅读(319) 评论(0) 推荐(0)
摘要: 深度优先搜索DFS 深度优先搜索DFS 排列数字 n-皇后问题 按位搜索 按行搜索 深度优先搜索的思想简单来说就是“一条道走到黑”,也被称为“暴力搜索”,常用于解决需要给出所有方案的问题,因为它的搜索顺序就是能够得到一个完整的搜索路径(方案)后回溯再去搜索其它的方案。 排列数字 题目链接:AcWin 阅读全文
posted @ 2022-12-09 22:07 S!no 阅读(26) 评论(0) 推荐(0)
摘要: 哈希表(Hash) 哈希表(Hash) 拉链法(开散列) 开放寻址法 字符串哈希 Hash 表又称为散列表,一般由 Hash 函数(散列函数)与链表结构共同实现。与离散化思想类似,当我们要对若干复杂信息进行统计时,可以用 Hash 函致把这些复杂信息映射到一个容易维护的值城内。因为值域变简单、范围变 阅读全文
posted @ 2022-12-09 22:07 S!no 阅读(155) 评论(0) 推荐(0)
摘要: 堆 堆是一种数据结构,主要包含以下操作: 插入一个数:将该数插到最后的位置,进行一次up操作 求集合中的最小值:输出堆顶元素 删除任意一个元素:将要删除的元素与末尾元素交换,然后进行一次up和down操作 修改任意一个元素:将某位置的元素修改,然后进行一次up和down操作 删除最小值:交换堆顶元素 阅读全文
posted @ 2022-12-09 22:07 S!no 阅读(87) 评论(0) 推荐(0)
摘要: 并查集(Disjoint-Set) 并查集(Disjoint-Set)是一种可以动态维护若干个不重叠的集合,并支持合并与查询的数据结构。详细地说,并查集包括如下两个基本操作: Get,查询一个元素属于哪个集合。 Merge,把两个集合合并成一个大集合。 为了具体实现并查集这种数据结构,我们首先需要定 阅读全文
posted @ 2022-12-09 22:07 S!no 阅读(205) 评论(0) 推荐(0)
摘要: Trie Trie(字典树)是一种用于实现字符串快速检索的多叉树结构。Trie 的每个节点都拥有若干个字符指针,若在插入或检索字符串时扫描到一个字符 c ,就沿着当前节点的 c 字符指针,走向该指针指向的节点。下面详细讨论 Trie 的基本操作过程: 初始化:一棵空 Trie 仅包含一个根结点,该点 阅读全文
posted @ 2022-12-09 22:07 S!no 阅读(35) 评论(0) 推荐(0)
摘要: KMP KMP 算法,又称模式匹配算法,能够在线性时间内判定字符串 $P[1 \sim N]$ 是否为字符串 $S[1 \sim M]$ 的子串。并求出字符串 $P$ 在字符串 $S$ 中各次出现的位置。 首先,一个 $O(NM)$ 的朴素做法是,尝试枚举字符串 $S$ 中的每个位置 $i$,把字符 阅读全文
posted @ 2022-12-09 22:06 S!no 阅读(62) 评论(0) 推荐(0)
摘要: 单调队列 单调队列算法很多时候用手写的模拟队列比较方便,因为很多时候需要双口出队的队列,主要是在队尾也有删除元素的需求。而模拟队列都是游标移动来限定队列中的所有元素,所以用模拟队列很自然的可以做到双端队列的操作。 单调队列一个经典应用就是求滑动窗口里的最大(或者最小)值。 算法步骤: 把该滑出的滑出 阅读全文
posted @ 2022-12-09 22:06 S!no 阅读(67) 评论(0) 推荐(0)
摘要: 单调栈 题目链接:AcWing 830. 单调栈 时间复杂度:$O(N)$ #include <iostream> using namespace std; const int N = 1e5 + 10; int n; int stk[N], tt; // 数组模拟栈,栈顶指针默认为0(空) int 阅读全文
posted @ 2022-12-09 22:06 S!no 阅读(25) 评论(0) 推荐(0)
摘要: 队列 数组模拟队列 题目链接:AcWing 829. 模拟队列 #include <iostream> using namespace std; const int N = 100010; int n; int q[N]; int hh = 0, tt = -1; void push(int x) 阅读全文
posted @ 2022-12-09 22:06 S!no 阅读(29) 评论(0) 推荐(0)
摘要: 栈 数组模拟栈 题目链接:AcWing 828. 模拟栈 #include <iostream> using namespace std; const int N = 100010; int n; int stk[N], tt; void push(int x) { stk[++ tt] = x; 阅读全文
posted @ 2022-12-09 22:06 S!no 阅读(28) 评论(0) 推荐(0)
摘要: 双链表 题目链接:AcWing 827. 双链表 #include <iostream> using namespace std; const int N = 100010; int e[N], l[N], r[N], idx; void init() { // 头节点为0,尾节点为1,插入的节点标 阅读全文
posted @ 2022-12-09 22:05 S!no 阅读(23) 评论(0) 推荐(0)
摘要: 单链表 题目链接:AcWing 826. 单链表 #include <iostream> using namespace std; const int N = 100010; int n; int e[N], ne[N], head, idx; void init() { idx = 0; head 阅读全文
posted @ 2022-12-09 22:05 S!no 阅读(17) 评论(0) 推荐(0)
摘要: 区间合并 区间合并问题也是一个贪心问题,由于比较常用所以单独拿出来。区间合并的解决方法是,把所有区间按照左端点 $l$ 从小到大排序,然后维护一个当前正在处理的区间 $[st,ed]$,如果遍历到区间和维护的区间有交集,就合并(能合则合),没有交集的时候,当前维护的区间就变成这个遍历到的区间。 这里 阅读全文
posted @ 2022-12-09 22:05 S!no 阅读(342) 评论(0) 推荐(0)
摘要: 离散化 离散化是一种辅助解决问题的操作,当问题中涉及的数据范围非常大,但是实际使用到的数据是比较少的。并且问题的求解是和它范围里的其它数据有关系的,那么可以将这些可能使用到的数据放到一起,排序去重,就将它们映射到了一个新的较小的范围里。 例如,下面几个数是在 $(-\infty, \infty)$ 阅读全文
posted @ 2022-12-09 22:05 S!no 阅读(94) 评论(0) 推荐(0)
摘要: 位操作 lowbit原理 根据计算机负数表示的特点,如一个数字原码是10001000,他的负数表示形式是补码,也就是反码+1,反码是01110111,加一则是01111000,二者按位与得到了1000,就是我们想要的lowbit操作 题目链接:AcWing 801. 二进制中1的个数 #includ 阅读全文
posted @ 2022-12-09 22:05 S!no 阅读(48) 评论(0) 推荐(0)
摘要: 双指针算法 双指针算法的核心思想就是在序列上找到这样一个性质,序列上的一个指针 $j$ 随着另一个指针 $i$ 的移动,是单向移动的,不会发生回退,这样就能在移动指针 $i$ 的时候去移动指针 $j$。由于两个指针都最多只会把序列遍历一遍,所以时间复杂度往往是从 $O(n^2)$ 优化到 $O(n) 阅读全文
posted @ 2022-12-09 22:05 S!no 阅读(68) 评论(0) 推荐(0)
摘要: 前缀和与差分 前缀和与差分 一维前缀和 差分 一维前缀和 前缀和可以用于快速计算一个序列的区间和,也有很多问题里不是直接用前缀和,但是借用了前缀和的思想。 用 $s[i]$ 表示 $a[0]+a[1]+\dots+a[i]$ 的和(所以称为前缀和),那么要计算区间 $[l, r]$ 的和,也就是计算 阅读全文
posted @ 2022-12-09 22:04 S!no 阅读(61) 评论(0) 推荐(0)
摘要: 高精度 高精度 高精度加法 高精度减法 高精度乘法 高精度除法 高精度加法 题目链接:AcWing 791. 高精度加法 题目描述 给定两个正整数(不含前导 0),计算它们的和。 输入格式 共两行,每行包含一个整数。 输出格式 共一行,包含所求的和。 数据范围 $1 \le$ 整数长度 $\le 1 阅读全文
posted @ 2022-12-09 22:04 S!no 阅读(89) 评论(0) 推荐(0)
摘要: 二分 二分法用于解决这样一类问题:一个区间能分成左右两部分,左半部分满足性质 $A$,右半部分不满足性质 $A$。问题的目标是求解这两部分的分界点。 所以二分法和区间里有没有单调性其实没什么关系,但是很多问题里是从单调性导出了上面的性质,上面的性质才是一个问题能用二分法求解的最本质的性质。 二分法每 阅读全文
posted @ 2022-12-09 22:00 S!no 阅读(128) 评论(0) 推荐(0)
摘要: 归并排序 归并排序的思想是基于分治法,其思路是: 将待排序区间平分成左右两半,左右两侧分别递归地做归并排序。 将这两个有序的区间合并(每次落一个较小的下来),就将这个区间排好序了。 归并排序相比快速排序,几乎没有什么难理解的边界问题。要注意代码中的q[i] <= q[j]时从左半边落下元素,如果改成 阅读全文
posted @ 2022-12-09 21:49 S!no 阅读(64) 评论(0) 推荐(0)
摘要: 快速排序 算法思想 快排的思想是基于分治法,其思路是: 确定分界点:给定要排序的数组q,先在数组中找一个数作为分界点值x,分界点可以取左边界值x = q[l],可以取右边界值x = q[r],可以取数组中间的数x = q[l + r >> 1],也可以随机取一个。 调整区间:将数组划分成两个区间,使 阅读全文
posted @ 2022-12-09 21:33 S!no 阅读(192) 评论(0) 推荐(0)