算法笔记
文章平均质量分 67
《算法笔记》学习笔记
pumpkin9841
这个作者很懒,什么都没留下…
展开
-
《算法笔记》10.3 图的遍历-算法笔记103图的遍历
10.3 图的遍历图的遍历是指对图的所有顶点按一定顺序进行访问,遍历方法一般有两种:深度优先搜索和广度优先搜索。10.3.1 DFS遍历图两个概念:连通分量:在无向图中,如果两个顶点之间可以相互到达(可以是通过一定路径间接到达),那么就称这两个顶点连通。如果图G(V,E)的任意两个顶点都连通,则称图G为连通图;否则,称图G为非连通图,且称其中的极大连通子图为连通分量。v1v2v3 , v4v5v6v7 , v8v9 形成三个连通分量强连通分量:在有向图中,如果两个顶点可以各自通过一条有向原创 2021-12-24 23:00:08 · 472 阅读 · 0 评论 -
《算法笔记》10.2 图的存储
10.2 图的存储一般来说,图的存储方式有两种:邻接矩阵和邻接表。这两种存储方式各有优势,需要在不同的情况下选择使用。10.2.1 邻接矩阵设图G(V,E)的顶点标号为0,1 ,…… ,N-1 ,那么可以令二维数组G[N][N]的两维分别表示图的顶点标号,即如果G[i][j]为1,则说明顶点i和顶点j之间有边;如果G[i][j]为0,则说明顶点i和顶点j之间不存在边,而这个二维数组G[N][N]则被称为邻接矩阵。另外,如果存在边权,则可以令G[i][j]存放边权,对不存在的边可以设边权为0、-1或是一原创 2021-12-24 22:58:29 · 508 阅读 · 0 评论 -
《算法笔记》10.1 图的定义和相关术语
10.1 图的定义和相关术语图由顶点(Vertex)和边(Edge)组成,每条边的两端都必须是图的两个顶点(可以是相同的点)。而记号G(V,E)表示图G的顶点集为V、边集为E。一般来说,图可分为有向图和无向图。有向图的所有边都有方向,即确定了顶点到顶点的一个指向;而无向图的所有边都是双向的,即无向边所连接的两个顶点可以相互到达。。在一些问题中,可以把无向图当作所有边都是正向和负向的两条有向边组成,这对解决一些问题很有帮助。顶点的度是指和该顶点相连的边的条数。特别是对于有向图来说,顶点的出边条数称为原创 2021-12-21 13:15:09 · 110 阅读 · 0 评论 -
《算法笔记》9.8 哈夫曼树
9.8 哈夫曼树9.8.1 哈夫曼树先介绍经典的合并果子问题。有n堆果子,每堆果子的质量已知,现在需要把这些果子合并成一堆,但是每次只能把两堆果子合并到一起,同时会消耗与两堆果子质量之和等值的体力。显然,在进行n-1次合并之后,就只剩下一堆了。为了尽可能节省体力,请设计出合并的次序方案,使得耗费的体力最少,并给出消耗的体力值。例如有3堆果子,质量依次为1、2、9,那么可以先将质量为1和2的果堆合并,新堆质量为3,因此耗费体力为3。接着,将新堆与原先的质量为9的果堆合并,又得到新的堆,质量为12,因原创 2021-12-21 13:06:57 · 4093 阅读 · 1 评论 -
《算法笔记》9.7 堆
9.7 堆9.7.1 堆的定义与基本操作堆是一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子结点的值。其中,如果父亲结点的值大于或等于孩子结点的值,那么称这样的堆为大顶堆,这时,每个结点的值都是以它为根结点的子树的最大值。相反,则为小顶堆。那么对于一个给定的初始序列,怎样把它建成一个堆呢?从最后一个元素开始,从下往上,从右往左。假设当前元素X,让x与X的孩子结点比较,如果发现比X更大的元素Y,则交换X与Y的位置,这样Y就成了根结点,而X则成为了孩子结点。交换之后让X继续与其孩子结点比较原创 2021-12-21 13:05:33 · 464 阅读 · 0 评论 -
《算法笔记》9.6 并查集
9.6 并查集9.6.1 并查集的定义并查集是一种维护集合的数据结构,他的名字中“并”、“查”、“集”分别取自Union(合并)、Find(查找)、Set(集合)。也就是说,并查集支持下面两个操作:合并:合并两个集合查找:判断两个元素是否在一个集合。那么并查集用什么实现呢?其实就是用一个数组:int father[N] ;其中father[i]表示元素i的父亲结点,而父亲结点本身也是这个集合内的元素。如果fatjer[i]==i,则说明元素i是该集合的根结点。但对同一个集合来说只存在一个原创 2021-12-21 13:04:06 · 193 阅读 · 0 评论 -
《算法笔记》9.5 平衡二叉树(AVL)
9.5 平衡二叉树(AVL)考虑使用序列{1,2,3,4,5}构建二叉查找树。显然这棵二叉查找树是链式的。那么,一旦需要对有10^5级别个递增元素的序列构建二叉查找树,也将会得到一棵长长链条式的树,此时对这棵树中结点进行查找的复杂度就会达到0(N),起不到使用二叉查找树来进行数据查询优化的目的。于是需要对树的结构进行调整,使树的高度在每次插入元素后仍然能保持O(logn)的级别,这样能让查询操作仍然是O(logn)的时间复杂度,于是就产生了平衡二叉树。AVL树仍然是一棵二叉查找树,只是在其基础上增加原创 2021-12-21 13:02:26 · 608 阅读 · 0 评论 -
《算法笔记》9.4 二叉查找树(BST)
9.4 二叉查找树(BST)9.4.1 二叉查找树的定义二叉查找树是一种特殊的二叉树,又称为排序二叉树、二叉搜索树、二叉排序树。二叉查找树的递归定义:要么二叉查找树是一颗空树要么二叉查找树由根结点、左子树和右子树组成,其中左子树和右子树都是二叉查找树,且左子树上所有结点的数据域均小于根结点数据域,右子树上所有节点数据域均大于根结点数据域。9.4.2 二叉查找树基本操作1.查找查找将会是从树根到查找结点的一条路径,故最坏复杂度是O(h),其中h是二叉查找树的高度。如果当前根节点root为原创 2021-12-21 13:00:28 · 349 阅读 · 0 评论 -
《算法笔记》9.3 树的遍历
9.3 树的遍历9.3.1 树的静态写法这里的“树”指的是一般意义上的树,即子节点个数不限且子节点没有先后次序的树。struct node{ typename data ; //数据域 vector<int> child ; //指针域,存放当前节点所有子节点下标}Node[maxn]; //节点数组,maxn为节点上限个数一般都是很人性化地给出了结点的编号,并且编号一定是0,1,…N-1(其中N为结点个数)或是1,2,.,N。在这种情况下,就不需要ne原创 2021-12-21 12:59:13 · 145 阅读 · 0 评论 -
《算法笔记》9.2 二叉树的遍历
9.2 二叉树的遍历二叉树的遍历是指通过一定顺序访问二叉树的所有节点。遍历方法一般有4种:先序遍历,中序遍历,后序遍历,层序遍历。其中,前三种一般使用DFS实现,而层序遍历一般使用BFS使用。先序遍历顺序为:根节点->左子树->右子树中序遍历顺序为:左子树->根节点->右子树后序遍历顺序为:左子树->右子树->根节点9.2.1 先序遍历先序遍历顺序为:根节点->左子树->右子树void preOrder( Node* root ){ if原创 2021-12-21 12:57:27 · 357 阅读 · 0 评论 -
《算法笔记》9.1 树与二叉树
9.1 树与二叉树9.1.1 树的性质树可以没有结点,这种情况下把树称为空树(empty tree)树的层次(layer)从根结点开始算起,即根结点为第一层,根结点子树的根结点为第二层,以此类推。把结点的子树棵数称为结点的度(degree),而树中结点的最大的度称为树的度(也称为树的宽度),例如图9-1中的三棵树的度分别为2、3、5.由于一条边连接两个结点,且树中不存在环,因此对有n个结点的树,边数一定是n-1,且满足连通、边数等于顶点数减1的结构一定是一棵树。叶子结点被定义为度为0的结点,因原创 2021-12-21 12:56:10 · 163 阅读 · 0 评论 -
《算法笔记》6.9 algorithm头文件下常用函数
6.9 algorithm头文件下常用函数6.9.1 max()、min()、abs()max(x,y)和min(x,y)分别返回x和y中的最大值和最小值,且参数必须是两个(可以是浮点数)。如果想要返回三个数x、y、z的最大值,可以使用max(x , max(y,z))的写法。abs(x)返回x的绝对值。注意:x必须是整数,浮点型的绝对值请用math头文件下的fabs()。6.9.2 swap()swap(x,y)用来交换x和y的值int a = 1 , b = 2 ;swap(a,b);/原创 2021-12-20 15:36:05 · 290 阅读 · 0 评论 -
《算法笔记》6.8 pair详解
6.8 pair详解pair是一个很实用的“小玩意”,当想要将两个任意类型的元素绑定在一起作为一个合成元素、又不想要因此定义结构体时,使用pair可以很方便地作为一个代替品。也就是说,pair实际上可以看作一个内部有两个元素的结构体,且这两个元素的类型可以指定。1. pair的定义要使用pair,需要添加头文件和命名空间。#include<utility>using namespace std ;由于map的内部实现涉及了pair,因此添加map头文件会自动添加utility头文件原创 2021-12-20 15:34:41 · 288 阅读 · 0 评论 -
《算法笔记》6.7 stack详解--suan-fa-bi-ji-67stack-xiang-jie
6.7 stack详解stack翻译为栈,是STL中实现的一个先进后出的容器。要使用stack,需要添加头文件和命名空间。#include<stack>using namespace std ;1. stack的定义与其他STL容器相同stack< typename > s ;2. stack容器元素的访问由于stack本身就是一种先进后出的限制性数据结构,在STL中stack只能通过**top()**来访问栈顶元素 st.top() ;3. stack常原创 2021-12-20 15:33:41 · 107 阅读 · 0 评论 -
《算法笔记》6.6 priority_queue详解
6.6 priority_queue详解priority_queue又称为优先队列,其底层是用堆来进行实现的。在优先队列中,队首元素一定是当前队列中优先级最高的那一个。当然,可以在任何时候往优先队列里面加入(push)元素,而优先队列底层的数据结构堆会随时调整结构,使得每次的队首元素都是优先级最大的。要使用queue,需先添加头文件和命名空间。#include<queue>using namespace std ;1. priority_queue的定义priority_queu原创 2021-12-20 15:32:29 · 996 阅读 · 0 评论 -
《算法笔记》6.5 queue详解
6.5 queue详解queue翻译为队列,在STL中主要则是实现了一个先进先出的容器。要使用queue,需先添加头文件和命名空间。#include<queue>using namespace std ;1. queue的定义queue< typename > name ;2. queue容器内元素的访问由于队列(queue)本身就是一种先进先出的限制性数据结构,因此在STL中只能通过front()来访问队首元素,或是通过back()来访问队尾元素。 queue&原创 2021-12-20 15:31:20 · 179 阅读 · 0 评论 -
《算法笔记》6.4 map详解-算法笔记64map详解
6.4 map详解map翻译为映射,也是常用的STL容器。map可以将任何基本类型(包括STL容器)映射到任何基本类型(包括STL容器),也就可以建立string类型到int类型的映射。如果要使用map,需要添加头文件和命名空间。#include<map>using namespace std ;1.map的定义单独定义一个mapmap<typename1 , typename2> mp ;而如果将字符串映射到整型,只能是string而不能是char数组map&原创 2021-12-20 15:29:49 · 296 阅读 · 0 评论 -
《算法笔记》6.3 string详解--suan-fa-bi-ji-63string-xiang-jie
6.3 string的常见用法详解如果要使用string,需要添加头文件和命名空间。#include<string>using namespace std ;注意:string.h与string是不一样的头文件。1. string定义方式string ste ;如果要初始化string str = "abc" ;2. string中内容访问(1)下标访问一般来说,可以直接像字符数组那样去访问stringfor( int i = 0 ; i < str.leng原创 2021-12-20 15:28:50 · 231 阅读 · 0 评论 -
《算法笔记》6.2 set详解
6.2 set详解set翻译为集合,是一个内部自动有序 且不含重复元素 的容器。如果使用set,需添加头文件和命名空间。#include<set>using namespace std ;1. 单独定义setset<typename> name ;基本定义与vector基本一样。2.set容器内元素访问set只能通过迭代器访问:set<typename>::iteartor it ;如for( auto it = st.begin() ;原创 2021-12-20 15:25:54 · 1186 阅读 · 0 评论 -
【算法笔记】笔记目录
《算法笔记》笔记原创 2021-12-20 15:15:15 · 1074 阅读 · 0 评论 -
《算法笔记》8.2 深度优先搜索DFS
深度优先搜索是一种枚举所有完整路径以遍历所有情况的搜索方法,记住使用递归来实现DFS的本质其实还是栈——使用递归时,系统会调用系统栈 来存放递归中的每一层状态。通过例子学习理解DFS题目一 有n件物品,每件物品的重量为w[i],价值为c[i],现在需要选出若干件物品放入一个容量为V的背包中,使得在选入背包的物品重量和不超过容量V的前提下,让背包中物品的价值之和最大,求最大价值,(1<n<20)题解 显然,每件物品都有装入背包与不装入背包两种选择,因此DFS函数的参数中必须记录当原创 2021-12-18 19:17:40 · 669 阅读 · 0 评论 -
《算法笔记》8.1 广度优先搜索BFS
广度优先算法一般由队列实现,且总是按照层次的顺序进行遍历,基本写法为(可做模板):void BFS(int s){ queue<int> q ; q.push(s) ; while( !q.empty() ){ 取出队首元素top ; 访问队首元素top ; 将队首元素出队 ; 将top的下一层节点中未曾入队的节点全部入队,并设置为已入队 ; }}题目给出一个m*n的矩阵,矩阵中的元素为0或1.称位置(x,y)与其上下原创 2021-12-18 19:15:02 · 654 阅读 · 0 评论 -
《算法笔记》7.3 链表处理
7.3 链表处理7.3.1 链表的概念线性表是一类很常用的数据结构,分为顺序表和链表。其中顺序表可以简单理解为数组。按正常方式定义一个数组时,计算机会从内存中取出一块连续的地址来存放给定长度的数组;而链表则是由若干个节点组成(每个节点代表一个元素),且节点在内存中的位置通常是不连续的。除此之外,链表的两个节点之间一般通过一个指针来从一个节点指向下一个节点,因此链表的节点一般由两部分构成,即数据域和指针域:struct Node{ typename data ; //数据域 Node* n原创 2021-12-18 19:12:37 · 693 阅读 · 0 评论 -
《算法笔记》6.1 vector详解
6.1 vector详解vector翻译为向量,可以理解为变长数组。如果使用vector,需要添加头文件和命名空间。#include<vector>using namespace std ;1.vector的定义单独定义一个vectorvector< typename > name ;或者初始化一个值为1,3,5的数组vector< int > name{1,3,5};和一维数组一样,typename可以是任何基本类型,如int , double原创 2021-12-18 19:11:08 · 627 阅读 · 0 评论 -
《算法笔记》5.5 质因子分解
5.5 质因子分解所谓质因子分解是指将一个正整数n写成一个或多个质数的乘积的形式,例如6=2x3,8=222,180=22335,或者我们也可以写成指数的形式,例如6=2!*31,8=2^3,180 =22335’。显然,由于最后都要归结到若干不同质数的乘积,因此不妨先把素数表打印出来。而打印素数表的方法上面已经阐述,下面我们主要就质因子分解本身进行讲解。注意:由于1本身不是素数,因此它没有质因子,下面的讲解是针对大于1的正整数来说的,而如果有些题目中要求对1进行处理,那么视题目条件而定来进行特判处理。原创 2021-12-18 19:10:16 · 569 阅读 · 0 评论 -
《算法笔记》5.4 素数
5.4 素数素数又称为质数,是指除了1和本身之外,不能被其他数整除的一类数。即对给定的正整数n,如果任意整数a(1<a<n),都有n % a != 0 ,那么n为素数。1既不是素数也不是合数5.4.1 素数的判断只需要判断n能否被2,3,4…(int)sqrt(n)中的一个整除,即可判断n是否为素数。时间复杂度为O(sqrt(n))。bool isPrime( int n ){ if ( n <= 1 ){ //特判 return false ;原创 2021-12-18 19:09:45 · 133 阅读 · 0 评论 -
《算法笔记》5.2 最大公约数与最小公倍数
5.2.1 最大公约数正整数a与b的最大公约数是指a与b的公约数中最大的那一个。例如4和6的最大公约数为2。一般用gcd(a,b)来表示a和b的最大公约数。而求解最大公约数常用欧几里得算法(辗转相除法)。欧几里得算法基于下面定理: 设a,b均为正整数,则 gcd(a,b) = gcd(b,a%b) 于是可以用下面代码求解:int gcd( int a , int b ){ if( b == 0 ){ return a ; } else{ re原创 2021-12-18 19:09:15 · 256 阅读 · 0 评论 -
《算法笔记》4.6 双指针(two pointers)
4.6.1 two pointers(双指针)以一个例子引入:给定一个递增的正整数序列和一个正整数M,求序列中的两个不同位置的数a和数b,使得他们的和恰好为M,输出所有满足条件的方案。例如给定序列{1,2,3,4,5,6}和正整数M=8,则存在2+6=8 , 3+5=8成立。最直接的双重遍历: for( int i = 0 ; i < n ; i++ ){ for( int j = i+1 ; j < n ; j++ ){ if( a[i] +原创 2021-12-18 19:08:28 · 559 阅读 · 0 评论 -
【LeetCode101】leetcode452 用最少数量的箭引爆气球
原题链接在选择用一根箭射穿的气球时,气球的结尾坐标很重要。结尾坐标内包含的气球越多,则一根箭能射穿的气球就越多。所以贪心策略就是优先找出一个气球的结尾坐标包含越多的气球。具体实现方法时,先把区间按照结尾的大小升序排序,每次选择当前气球与前面的所有气球都有重复区间,即当前气球的开始坐标小于前面的任何一个气球的结尾坐标(表示当前气球跟前面的气球能被用一根箭射穿),若当前气球不能跟前面的气球被同一根箭射穿,则令index等于当前气球下标(后面的气球不用跟index之前的气球比较了)。代码class Sol原创 2021-12-09 22:34:56 · 174 阅读 · 0 评论