数据结构与算法知识基础以及进阶
文章平均质量分 62
主要讲讲一些常见的数据结构以及算法知识
1.01
这个作者很懒,什么都没留下…
展开
-
基础算法集合
关于求解子串、子序列问题回文子串以及子序列问题最大乘积,最大和---------连续子数组最长连续不重复子数组最长公共子序列以及最长公共子串最长上升子序列原创 2021-02-01 09:16:47 · 92 阅读 · 0 评论 -
常用排序算法稳定性
前言:什么是稳定性?定义:排序前后两个相等的数相对位置不变,则算法稳定。总述:各排序算法的稳定性:堆排序、快速排序、希尔排序、直接选择排序不是稳定的排序算法;基数排序、冒泡排序、直接插入排序、折半插入排序、归并排序是稳定的排序算法。一、冒泡排序小的元素往前调或者把大的元素往后调;比较是相邻的两个元素,那么交换也发生在这两个元素之间;很显然是稳定性排序算法。二、选择排序每个位置选择当前元素最小的;在一趟选择中,如果当前元素比一个元素小,而该小的元素原创 2021-04-11 23:44:02 · 3475 阅读 · 0 评论 -
跳跃表( 也是Redis中 sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序 )
1. 跳跃表的原理 学过数据结构的都知道,在单链表中查询一个元素的时间复杂度为O(n),即使该单链表是有序的,我们也不能通过2分的方式缩减时间复杂度。 如上图,我们要查询元素为55的结点,必须从头结点,循环遍历到最后一个节点,不算-INF(负无穷)一共查询8次。那么用什么办法能够用更少的次数访问55呢?最直观的...转载 2021-02-19 15:49:49 · 465 阅读 · 2 评论 -
最大乘积,最大和---------连续子数组
最大连续乘积子数组遍历数组时计算当前最大值,不断更新令imax为当前最大值,则当前最大值为 imax = max(imax * nums[i], nums[i])由于存在负数,那么会导致最大的变最小的,最小的变最大的。因此还需要维护当前最小值imin,imin = min(imin * nums[i], nums[i])当负数出现时则imax与imin进行交换再进行下一步计算时间复杂度:O(n)class Solution {public: int maxProduct(vector原创 2021-01-30 11:58:27 · 94 阅读 · 0 评论 -
最长连续不重复子串
题目内容描述给定一个字符串,找出不含有重复字符的最长子串的长度。示例:给定 “abcabcbb” ,没有重复字符的最长子串是 “abc” ,那么长度就是3。给定 “bbbbb” ,最长的子串就是 “b” ,长度是1。给定 “pwwkew” ,最长子串是 “wke” ,长度是3。请注意答案必须是一个子串,”pwke” 是 子序列 而不是子串。代码:# include <iostream># include <string>using namespace std;i原创 2021-01-28 09:13:06 · 733 阅读 · 0 评论 -
排列组合方案的全输出-------dfs法
实现指数型枚举等价于每个整数选与不选,总的方案数就是2^n种// 递归版本# include <iostream># include <vector># include <string>using namespace std;vector<int> q;void dfs(int i,int n){ if(i == n+1){ //边界 for(auto i:q){ cout<&l原创 2020-12-13 20:45:43 · 279 阅读 · 0 评论 -
图论------有向图的连通性问题
前言:一些概念需要我们理解一下,以便更好地进行下面的内容。在有向图G中,如果两个顶点间至少存在一条互相可达路径,称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。非强连通图有向图的极大强连通子图,称为强连通分量(strongly connected components)。很明显强连通分量出现在有向有环图中,每一个连通的分量都可以被当作是强连通分量。如左下图每一个虚线框内都是一个强连通分量(SCC),右下图则将强连通分量当作一个结点原创 2020-09-22 16:44:02 · 5867 阅读 · 0 评论 -
字符串算法----kmp算法
前言:此篇是转载别人的博客,原地址:请点击!写给自己的话:理解next[]数组的意义,next[i]表示以i为结尾的最大的相同公共(真)前后缀的长度前缀是可以包括它自己本身,真前缀是不包括它自己本身//自己写的代码# include <iostream>using namespace std;const int N = 1e5+10;const int M = 1e6+10;char s[N];char t[M];int nex[N];int main(void)原创 2020-09-10 23:36:40 · 134 阅读 · 0 评论 -
最长公共子序列以及最长公共子串
前言:# include <iostream># include <string># include <algorithm># include <cstring># include <vector>using namespace std;const int N = 1100;int dp[N][N];int main(void){ string s,t; cin>>s>>t; f原创 2020-09-08 16:36:24 · 288 阅读 · 0 评论 -
RMQ问题解法之ST倍增
前言:RMQ (Range Minimum/Maximum Query):对于长度为n的数组A,回答若干询问RMQ(A,i,j)(i,j<=n-1),返回数组A中下标在i,j范围内的最小(大)值,也就是说,RMQ问题是指求区间最值的问题。ST算法ST算法是一种更加高效的算法,在O(nlogn)的预处理代价,以O(1)的时间复杂度在线回答“数列A中下标在left~right”之间的数的最大值是多少?"这样的区间最值问题。采用的是动态规划的思想。要求区间[l,r]的最值,我们将其区间细分成两个长度原创 2020-09-01 23:51:22 · 167 阅读 · 0 评论 -
倍增法应用------LCA(树上最近公共祖先)
前言:LCA (Least Common Ancestors) ,即最近公共祖先,给定一棵有根树,若结点z既是节点x的祖先,也是节点y的祖先,则称z是x,y的公共祖先。在x,y的所有公共祖先中,深度最大的一个称为x,y的最近公共祖先,记为LCA(x,y)。LCA(x,y)是x到根的路径与y到根的路径的交会点。它也是x与y之间路径上深度最小的节点。树上倍增法树上倍增法设F[x][k]表示x的2k{2^k}2k辈祖先,即从x向根节点走2k{2^k}2k步到达的节点。特别地,若该节点不存在,则令F[x原创 2020-09-01 17:05:42 · 193 阅读 · 0 评论 -
图论-----------欧拉通路以及欧拉回路
前言:我们先来了解一下概念:欧拉通路:通过图中所有边一次且仅一次行遍所有顶点的通路欧拉回路:通过图中所有边一次且仅一次行遍所有顶点的回路欧拉图:具有欧拉回路的图半欧拉图:具有欧拉通路而无欧拉回路的图奇度点:与点相连的边的数目为奇数的点偶度点:与点相连的边的数目为偶数的点判定无向图欧拉通路:图是连通的,图中只有两个奇度点,分别是欧拉通路的两个端点(就是起点和终点),对于欧拉通路,除起点、终点外,每个点如果进入,显然一定要出去,因此都是偶点欧拉回路:图是连通的,点均为偶度点,对原创 2020-08-27 22:15:08 · 1716 阅读 · 0 评论 -
图论--------拓扑排序相关讲解以及题目
前言:引用百度百科的话:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边<u,v>∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。简单来说:一个图的所有节点排序,使得每一条有向边(u,v)对应的u都排在v的前面原创 2020-08-23 20:27:56 · 1353 阅读 · 0 评论 -
回文子串(Manacher‘s Algorithm马拉车算法)以及回文子序列
前言:我们先了解回文串,顾名思义就是前后翻转都一样,这样的字符串就是回文串,如aba,abba等判断回文串的方法方法一:最简单的方法就是用原来的字符串跟翻转后的字符串进行比较,只要有一对字符不相等,那么就不是回文串。代码如下:在这里插入代码片方法二:利用栈来解决,但是这里要注意奇偶问题,也就是回文串的个数的总数是奇数还是偶数,这里要判断一下。假设len为字符串的个数,如果(len&1),那么我们就需要往栈中添加前1到len/2个元素,然后弹栈进行检查,假设压栈的最后原创 2020-08-20 10:17:32 · 521 阅读 · 0 评论 -
数的全排列以及组合问题(DFS)
前言:我们得知道一个事实,当我们用下面的解法解答问题时,要知道能解答的数据范围是很小的,比如1到10或者15这些小范围,因为这是都是以指数级别的增长时间复杂度。假如给你三个数字123,要求你进行数字的全排列,你会怎么做?简单的思路:用三个for循环,采用枚举法,再用条件进行判断。什么是枚举法?将问题的所有可能的答案一一列举,然后根据条件判断此答案是否合适,合适就保留,不合适就丢弃。例如:找出1到100之间的素数,需要将1到100之间的所有整数进行判断。枚举算法因为要列举问题的所有可能的答案,原创 2020-08-11 20:11:20 · 373 阅读 · 0 评论 -
AC自动机----多模式匹配(KMP的进化版)
本文转载,详细请点击! 首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一。一个常见的例子就是给出n个单词,再给出一段包含m个字符的文章,让你找出有多少个单词在文章里出现过。要搞懂AC自动机,先得有模式树(字典树)Trie和KMP模式匹配算法的基础知识。KMP算法是单模式串的字符匹配算法,AC自动机是多模式串的字符匹配算法。AC自动机和字典树的关系比较大,所以先来简单的了解下字典树Trie。字典树又称单词查找转载 2020-07-30 22:22:40 · 218 阅读 · 0 评论 -
最长上升子序列
给定一个长度为N的数列,求数值严格单调递增的子序列的长度最长是多少。输入格式第一行包含整数N。第二行包含N个整数,表示完整序列。输出格式输出一个整数,表示最大长度。数据范围1≤N≤1000,−109≤数列中的数≤109输入样例:73 1 2 1 8 5 6输出样例:4上图这里的话就开个一维数组,f[i]表示所有以第i个数结尾上升子序列代码:# include <iostream># include <cmath>using namespace原创 2020-07-29 22:36:52 · 137 阅读 · 0 评论 -
排序算法------栈排序
前言:栈排序,是利用栈的特性进行排序的,这里就是指先进后出这个特性。例题 :这里可以允许用到两个栈,也就是多用一个辅助栈。具体思路:就是循环遍历元素,当发现入栈的元素x要比栈顶要大的时候,则循环将栈顶小于x的元素放到辅助栈中,然后把x入栈,最后把辅助栈的元素重新入栈。# include <iostream># include <algorithm># include <cstdlib># include <cstdio># include原创 2020-07-15 22:03:24 · 1982 阅读 · 0 评论 -
基础算法知识点------单调队列
单调队列原创 2020-07-14 21:28:59 · 1399 阅读 · 0 评论 -
RMQ问题--------树状数组
前言:简述一下RMQ问题,就是区间和或者区间最值,当然有很多方法可以做这个RMQ问题,这里主要讲讲树状数组这个结构体来解决此问题。最常解决两类问题:No.1 区间的查询和单点的修改No.2 区间的最大值和最小值的差值(用两个数组来存,一个存最大值,一个存最小),也可以是求区间最大值,最小值。树状数组浅析首先我们得知道,这个数据结构其实就是用数组来做的,只不过我们规范数组的用法,就成了解决问题的好帮手,上张图看看,就把此数组理解成树即可具体说说数组的作用NO.1树状数组最基本的功原创 2020-07-11 22:31:56 · 544 阅读 · 0 评论 -
排序算法------基数排序
//自己写的c++代码 基数排序# include <iostream># include <algorithm># include <vector># include <cstdlib>using namespace std;int a[100];vector<vector<int> > q(10);int main(void){ int n; cin>>n; srand(unsigned(t转载 2020-07-02 17:05:55 · 101 阅读 · 0 评论 -
(不入流的排序算法)------猴子排序
前言:这个算法其实没啥使用,现在常用的排序算法(内部排序)还是那十大排序算法,什么快排,归并,堆等等,这个算法可以了解了解。猴子排序猴子代表乱的意思,猴子排序的意思就是随机排序,直到有序为止。主要用到随机化的知识,也就是随机选取一个下标为x的时候用到随机化(把挑选的下标用rand()随机出来)这个算法的时间复杂度是不稳定的,可能O(1),最坏O(n*n,这是有随机化的特点决定的,也是看人品的时刻,hh…# include <iostream># include <cstdli原创 2020-06-29 17:00:46 · 1578 阅读 · 0 评论 -
并查集的一些讲解
简述在计算机科学中,并查集 是一种树形的数据结构,用于处理不交集的合并(union)及查询(find)问题。并查集 对于查询两个节点的 连接状态 非常高效。对于两个节点是否相连,也可以通过求解 查询路径 来解决, 也就是说如果两个点的连接路径都求出来了,自然也就知道两个点是否相连了,但是如果仅仅想知道两个点是否相连,使用 路径问题 来处理效率会低一些,并查集 就是一个很好的选择。这里的话,简单点来说,用基础版的并查集,你可以快速判断某两个点是否在一个集合里,那么进阶版的并查集就有拓展域并查集和边带权并原创 2020-07-14 21:47:20 · 228 阅读 · 0 评论 -
双指针算法以及一些典型例题
一、双指针算法两种常见的问题分类:(1)对于两个序列,维护某种次序,比如归并中合并两个有序序列的操作(2)对于一个序列,用两个指针维护一段区间如图:注意,这里虽然说双指针,但不代表是真正的两个指针,你可以理解为两个变量i,j但是这两个变量i,j它们是一直向前行进的,是不会后退,就拿KMP来说,其实它也用到双指针的思想以及归并排序当中的合并两个区间的代码。尺取法,这个说到底就是双指针思想衍生出来的,那什么是尺取法呢?你就理解为一把可长可短的尺子,推进你要遍历的元素尺取法:顾名思义,像尺子一样原创 2020-06-23 22:41:23 · 529 阅读 · 0 评论 -
排序算法------堆排序
# include <iostream>using namespace std;int a[1000];void Siftdown(int i,int n){ int t,flag=1; while(i*2<=n && flag){ if(a[i]>a[i*2]) t = i*2; else t = i; if(i*2+1 <= n && a[t] > a[i*2+1]原创 2020-06-02 21:14:26 · 93 阅读 · 0 评论 -
插入排序算法解析以及希尔排序
前言:插入排序(稳定排序)的基本思想是:将数组的第一个数认为是有序数组,从后往前(从前往后)扫描该有序数组,把数组中其余n-1个数,根据数值的大小,插入到有序数组中,直至数组中的所有数有序排列为止。这样的话,n个元素需要进行n-1趟排序。时间复杂度为O(n*n);但是在同样的数据下,要比冒泡法以及选择排序法好得多。有位博主写得很Q的解析,请点击# include <iostream># include <vector># include <algorithm>原创 2020-05-31 11:44:57 · 124 阅读 · 0 评论 -
排序算法--------快速排序
快速排序这里有位博主写的快排解析,还不错,直接点击查看自己实现的普通版快排# include <iostream>using namespace std;int a[90];void dfs(int left,int right){ //快排讲到底就是递归,当然还有非递归的 if(left>=right) return ; int i,j,st; i = left,j = right,st = a[left]; //选最左边的数为基准数原创 2020-05-30 20:15:25 · 143 阅读 · 0 评论 -
数论篇-----拓展欧几里得
前言:什么是欧几里得算法?一看到这个词,可能想不出什么,那么我们换个说法,就是怎么求两个数的最大公因数,这个相信我们都会,什么辗转相除法,更相减损术等等。欧几里得算法,也称辗转相除法,是求最大公约数的一种方法。它的具体做法是:用较大数除以较小数,再用出现的余数(第一余数)去除除数,再用出现的余数(第二余数)去除第一余数,如此反复,直到最后余数是0为止。如果是求两个数的最大公约数,那么最后的除数...原创 2020-03-23 23:46:38 · 149 阅读 · 0 评论 -
数论篇-------欧拉函数(简记)
欧拉函数特别的,1的欧拉函数是1思路:你会发现,利用到算术基本定理,然后再乘以每个质因数的式子即可例题:给定n个正整数ai,请你求出每个数的欧拉函数。# include <iostream># include <algorithm>using namespace std;int main(void){ int t; cin>>t...原创 2020-03-21 22:59:37 · 431 阅读 · 0 评论 -
数论篇-----约数
前言:在进入主题之前,我们先来讲一个东西-------算术基本定理!主要是后面的知识点有用到这个定理。算术基本定理(唯一分解定理)算术基本定理,又称为正整数的唯一分解定理,即:每个大于1的自然数均可写为质数的积,而且这些素因子按大小排列之后,写法仅有一种方式。例如:若不考虑排列的顺序,正整数分解为素数乘积的方式是唯一的。算术基本定理是初等数论中一个基本的定理,也是许多其他定理的逻辑...原创 2020-03-21 22:40:27 · 427 阅读 · 0 评论 -
数论篇------组合计数问题
前言:------ 相信大家都知道排列组合问题,这个在我们高中时就已经学过了,在这里我主要讨论组合计数在算法中怎么实现。了解排列组合的戳这里首先我们先来了解一些东西,如图所示:接下来就拿例题来讲解例题一:给定n组询问,每组询问给定两个整数a,b,请你输出Cba mod (109+7)的值。输入格式第一行包含整数n。接下来n行,每行包含一组a和b。输出格式共n行,每行...原创 2020-03-19 22:57:22 · 590 阅读 · 0 评论 -
公平组合游戏以及SG函数
一、公平组合游戏定义1.公平组合游戏ICG若一个游戏满足:由两名玩家交替行动;在游戏进程的任意时刻,可以执行的合法行动与轮到哪名玩家无关:不能行动的玩家判负;则称该游戏为一个公平组合游戏。NIM博弈属于公平组合游戏,但城建的棋类游戏,比如围棋,就不是公平组合游戏。因为围棋交战双方分别只能落黑子和白子,胜负判定也比较复杂,不满足条件2和条件3。2.有向图游戏:给定一个有向无环图,图中有一个...原创 2020-03-17 23:52:27 · 295 阅读 · 0 评论 -
数论篇------博弈论
引语:什么是博弈?通俗地讲, 博弈就是指游戏中的一种选择策略的研究。在他们都没有失误并采取最优策略后,一定有一个人胜出,在知道初状态及规则的情况下,求解最终必胜的初状态(即何人胜出)的一类问题的理论及方法。**四大博弈:Nim博弈,巴什博弈,斐波那契博弈,威佐夫博弈。这里的话我们注重讲讲*Nim博弈论*的问题Nim博弈问题尼姆博弈指的是这样一个博弈游戏:有任意堆物品,每堆物品的个数是...原创 2020-03-17 23:55:45 · 382 阅读 · 0 评论 -
数论篇------大数运算
想必加减乘除这个运算,大家都知道,也很简单。但是遇到大数运算时呢?该怎么进行加法,减法,乘法,除法呢?**前提首先要明确的一点是,大数都是用字符串来做的,输入输出都是,所以这里一定会有个函数是将字符串转为数字的,这里的话是用到vector 容器来存储,并且容器的低位存的是数字的低位,也就是倒着存储,比如521(五百二十一),在容器就为125这样。 **其基本操作都是相加减乘除后,进位。...原创 2020-03-12 11:37:49 · 241 阅读 · 0 评论 -
数论-----素数篇
引言:首先我们得明白什么是素数?从定义出发,素数又称质数。所谓素数是指除了1和它本身以外,不能被任何整数整除的数,例如17就是素数,因为它不能被2~16的任一整数整除判断一个数是否是素数的解决方法:朴素的方法(直接从2到n遍历,一旦发现某个数能被n整除,则一定是合数,从而不满足素数的定义)bool check(int n){ for(int i=2;i<=n;++i){ i...原创 2020-03-09 17:19:40 · 521 阅读 · 0 评论 -
浮点数
之前做题遇到过怎么判断A+B=C问题,思维定位了,直接这么判断,这样子是不能通过的;后来上网搜了一下才知道浮点数的存储,才突然明白这个细节问题.在计算机中实数的相等问题,如浮点数A,B,C;不能直接A+B=C,这样判断,必须用到fabs()即求浮点数x的绝对值的函数,在头文件加上# include &lt;math.h&gt;字样。如代码#include&lt;stdio.h&gt;#inc...原创 2019-01-25 20:48:08 · 144 阅读 · 0 评论