算法笔记(胡凡)
文章平均质量分 84
摘录算法笔记一书中的知识点,回顾并学习
冷眼观world
社畜
展开
-
排序
1.二路归并排序时间复杂度:O(nlogn)空间复杂度:O(n)基于“归并”思想的排序方法。原理:将序列两两分组,分为⌈n/2⌉个组,组内单独排序;然后两两归并,生成⌈n/4⌉个组,组内再单独排序,以此类推,直到只剩一个组为止。举例:数组:{66, 12, 33, 57, 64, 27, 18}第一趟:两两分组{66, 12}, {33, 57}, {64, 27}, {18}排序后...原创 2020-04-14 23:42:33 · 162 阅读 · 0 评论 -
散列
常用的散列函数方法折叠法将关键字从左到右分割成位数相等的几部分(注意最后一部分位数不够时可以短些)然后将这几部分叠加求和,并按散列表表长,取后几位作为散列地址假设关键字是 9876543210,散列表表长为三位则我们可以将它分为四组 987|654|321|0然后将它们叠加求和 987+654+321+0=1962再取后 3 位得到散列地址即为 962适合位数较多情况平方取中法...原创 2020-04-16 15:02:32 · 170 阅读 · 0 评论 -
递归——全排列、N皇后
全排列问题全排列指n个整数能形成的所有排列。比如1、2、3就能形成(123) (132) (213) (231) (312) (321)这6个全排列现在用递归解决全排列题目“输出1 ~ n这n个整数的全排列”可以分成若干子问题“以1开头的全排列”、“以2开头的全排列”…...原创 2020-04-17 21:52:05 · 167 阅读 · 0 评论 -
区间贪心
给定N个开区间(x, y),从中选择尽可能多的开区间,使得这些开区间两两没有交集。比如(1, 3)、(2, 4)、(3, 5)、(6, 7),可以选择最多三个区间(1, 3)、(3, 5)、(6, 7),它们互相没有交集。贪心策略:考虑最简单情况,如果开区间I1被开区间I2包含,那么此时最好的选择是I1,因为选更短的就能有更大的空间取容纳其他空间。I1 x...原创 2020-04-18 14:08:22 · 169 阅读 · 0 评论 -
二分
首先使最简单的,二分查找。二分查找是基于有序序列的查找算法,每一步都可以去除当前区间中一半的元素,因此时间复杂度O(logn)。int binarysearch(vector<int> &vec, int n){ int left = 0, right = vec.size() - 1; int mid = (left + right) / 2; while (lef...原创 2020-04-22 16:49:12 · 269 阅读 · 0 评论 -
双指针
假设一个递增的正整数序列和一个正整数M,求序列中两个不同位置的数a和b,使他们的和七号为M,输出所有满足条件的方案。比如:{1, 2, 3, 4, 5, 6}和M=8,输出2 + 6 = 8, 3 + 5 = 8.本题最暴力的方法就是二重循环枚举序列中整数a和b,判断和是否为M,时间复杂度O(n2)。复杂度高的原因:对于一个确定的arr[i]来说,如果当前arr[j]满足arr[i] +...原创 2020-06-21 17:46:33 · 130 阅读 · 1 评论 -
随机选择算法
讨论一种常见的算法问题,topK问题,即从一个无序数组中求出第K大的数,比如数组{5, 12, 7, 2, 9, 3},第三打的数是5,第5大的数是9。首先最简单的方法是先排序,然后直接取出第K大元素,但是样最好的时间复杂度也得到O(nlogn)。随机选择算法可以到O(n)的复杂度。...原创 2020-06-17 11:38:48 · 480 阅读 · 0 评论 -
最大公约数和最小公倍数
最大公约数a和b的最大公约数指a与b的所有公约数中最大的那个公约数,比如4和6的最大公约数是2。求解最大公约数常用欧几里得算法(即辗转相除法)欧几里得算法基于这个定理:设a、b是正整数,则gcd(a, b) = gcd(b, a % b);证明:设a = kb + r,其中k和r分别为a除以b得到的商和余数则有r = a - kb成立设d为a和b的一个公约数那么由r = a -...原创 2020-04-19 00:37:59 · 981 阅读 · 1 评论 -
分数的四则运算
分数的表示和化简分数的表示用结构体存储只有分子和分母的分数:struct Fraction{ int up; //分子 int down; //分母}需要对这种表示制定三项规则:down必须为非负数,如果分数是负数的情况,那就令分子为负数如果该分数是0,那就令分子为0,分母为1分子和分母没有除1以外的公约数分数的化简按照上面的三项规定来化简:如果down为负数,...原创 2020-04-19 15:00:13 · 593 阅读 · 0 评论 -
素数
素数的判断判断一个数n是否为素数,就需要判断n是否能被2、3…、n-1中的一个数整除。只有都不能整除n,n才能判定为素数。bool isPrime(int n){ if (n <= 1) return false; for (int i = 2; i < n; i++) { if(n % i == 0) retu...原创 2020-04-19 18:30:35 · 2217 阅读 · 0 评论 -
质因子分解
质因子分解是指将一个正整数n写成一个或多个素数的乘积形式,比如6 = 2 * 3、8 = 2 * 2 * 2、180 = 2 * 2 * 3 * 3 * 5。或者也可以写成指数形式,6 = 21 * 31、8 = 23、180 = 22 * 32 * 51。最后因为都要归结到若干不同素数的乘积,因此不妨先把素数表打印出来。用上一章讲的方法就可以。因为每个质因子都可以不止出现一次,因此不妨定...原创 2020-04-20 22:06:41 · 1308 阅读 · 0 评论 -
大整数运算
大整数的存储比如2358133可以存储在int数组d[1000]中,d[0] = 3,d[1] = 1,d[2] = 8…即整数的高位存储在数组到高位,整数的低位存储在数组的低位。不反过来存储的原因是进行运算的时候都是从低位到高位枚举,顺位存储和这种思维相合。这时候还有要注意一个问题:如果把整数按字符串%s读入时,和上面的存储顺序是相反的,因此要存到d数组时得反转一下。...原创 2020-04-26 16:25:00 · 690 阅读 · 0 评论 -
深度优先搜索
深度优先搜索是一种枚举所有完整路径以遍历所有情况的搜索方法。背包问题:在n件物品中,每件物品的重量是w[i],价值为c[i]。现在需要选出若干件物品放入一个容量为V的背包中,使得再选入背包的物品重量和不超过容量V的前提下,让背包中的物品的价值之和最大,求最大价值。(1 <= n <= 20)模仿书中迷宫的例子寻找“岔路口”和“死胡同”,对每件物品都有选或者不选两个选择,这就是...原创 2020-04-29 19:49:03 · 160 阅读 · 0 评论 -
树
这里采用将数据先全部存储数组vec中,再构造树#include <iostream>#include <cstdlib>#include <vector>#include <queue>#include <algorithm>using namespace std;struct node{ int val; node* left; node* right; node(int v) : val(v), left(NULL),原创 2020-07-04 21:47:41 · 240 阅读 · 0 评论 -
并查集
定义利用一个数组实现并查集int father[N];其中father[i]表示元素i的父亲结点,比如father[1] = 2说明1的父亲结点是元素2;而如果father[i] == i则说明i是该集合的根节点。father[1] = 1;father[2] = 1;father[3] = 2;father[4] = 2;父亲关系图: 1 | 2 / \ 3 4基本操作初始化刚开始每个元素都是独立的集原创 2020-07-05 15:44:42 · 147 阅读 · 0 评论 -
图
快速导航图的存储DFS邻接矩阵版邻接表法为了方便处理,一般使用vector来存储图。图的存储如果选择邻接矩阵法则使用一个二维数组vector<int, vector<int> > G存储图;如果选择邻接表法:不需要边权则声明vector<int> G[N];,然后添加由1到3的有向边G.push_back(3);需要边权则先使用结构体node来表示图的结点:struct node{ int v; //边终点编号 int w; //边权 node(in原创 2020-08-20 00:46:43 · 351 阅读 · 0 评论 -
最小生成树
快速导航Prim算法邻接矩阵版邻接表版Kruskal算法Prim算法基本思想是对图G[V, E]设置集合S来存放已被访问的顶点,然后执行n次以下两个步骤每次从集合V-S(即未访问的点)中选择和集合S最近的一个顶点u,访问u并将其加入集合S,同时把这条离集合S最近的边加入最小生成树中令顶点u作为集合S和集合V-S连接的接口,优化从u能到达的未访问顶点v与集合S的最短距离实现该算法需要两个概念:集合S的实现实现方法和Dijkstra中相同,用一个bool型数组(或map)visit[]来表原创 2020-10-21 13:36:10 · 264 阅读 · 0 评论 -
动态规划(未完待续)
动态规划是一种用来解决一类最优化问题的算法思想,动态规划将一复杂的问题分解成若干子问题,通过综合子问题的最优解来得到原问题的最优解。动态规划能将每个求解过的子问题的解记录下来,这样下一次碰到同样的子问题时就可以直接哟ing之前记录的结果,而不用重复计算。动态规划的递归写法通过一个经典的递归——斐波那契数列来理解动态规划是如何记录子问题的解来避免下次遇到相同的子问题时的重复计算的.先看斐波那契数列代码:int Fibonacci(int n){ if (n == 0 || n == 1) re原创 2020-11-21 15:34:39 · 350 阅读 · 0 评论 -
分块思想
还是用问题引入:给出一个非负整数序列A,元素个数为N(N<=105,A[i]<=105),在有可能随时添加或删除元素的情况下, 实时查询序列中第K大的元素(即把序列元素从小到大排序后从左到右的第K个元素,比如{2, 7, 5, 1, 6}中第3大元素是5,但是插入元素4之后第3大的元素就是4了)在查询过程中元素可能发生改变(插入、删除等),就称为在线查询,反之叫离线查询。上面的问题就是在线查询。如果直接暴力做法来做,在每次添加或删除元素之后就要用O(n)的时间复杂度来移动序列元素,效率原创 2021-01-13 20:36:31 · 179 阅读 · 0 评论