
算法基础
文章平均质量分 64
Alps1992
我希望自己变得更优秀。
展开
-
算法学习 - 01背包问题(动态规划C++)
动态规划01背包问题描述求解思路代码实现放入哪些物品代码动态规划我在上一篇博客里已经讲了一点动态规划了,传送门:算法学习 - 动态规划(DP问题)(C++)这里说一下,遇到动态规划应该如何去想,才能找到解决办法。最主要的其实是要找状态转移的方程,例如上一篇博客里面,找的就是当前两条生产线的第i个station的最短时间和上一时刻的时间关系。minTime(station[1][i]) =原创 2015-04-28 21:09:53 · 11085 阅读 · 3 评论 -
算法基础 - 多源点最短路径(Floyd算法)
Floyd算法Floyd算法又称为插点法,是一种用于寻找给定的加权图中多源点之间最短路径的算法。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。思路路径矩阵通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。 从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式原创 2016-05-11 02:27:44 · 7248 阅读 · 0 评论 -
算法学习 - Dijkstra(迪杰斯特拉)算法学习
Dijkstra算法其实Dijkstra是单源点最短路径的基础算法,这个算法的目的就是找到一个图中的某个点V到这个图中其他点的最短路径。条件 有向图没有负权值路径 时间复杂度:O(E) + O(V^2) = O(V^2) 当图是稠密的时候和稀疏的时候时间复杂度还是有点差别的。 代码实现其实这个还挺简单的,单源点最短路径还有一个Bellman-Ford算法,以后在写,比较简单。D原创 2015-03-11 11:25:59 · 2963 阅读 · 0 评论 -
算法基础 - 非递归使用栈遍历树
一直觉得非递归遍历树也很简单,就一直没有写,小问题栽了大跟头啊,继续努力吧。这里说一下非递归的思想主要是怎么做,使用栈空间和使用递归比较像,但是有一些细节不一样,因为while循环可能在后序遍历的时候重复压栈。下面写一下三种遍历的代码:先序遍历void preorderTree(TreeNode * root){ stack<TreeNode *> st; TreeNode *原创 2016-04-26 09:44:31 · 1987 阅读 · 0 评论 -
算法基础 - 树状数组(binary indexed tree)
定义 树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值。 这种数据结构(算法)并没有C++和Java的库支持,需要自己手动实现。在Competit原创 2016-03-09 22:56:55 · 1742 阅读 · 0 评论 -
算法学习 - 动态规划(DP问题)装配线问题(C++)
这几天一直再看,觉得看懂了一些,先记下来。动态规划动态规划是运筹学的一个方向,就是把多级最优化问题分解成一系列的单阶问题。在不断增加的过程中,不断的计算当前问题的最优解。一般分为如下四个部分:线性动规:拦截导弹,合唱队形,挖地雷,建学校,剑客决斗等;区域动规:石子合并, 加分二叉树,统计单词个数,炮兵布阵等;树形动规:贪吃的九头龙,二分查找树,聚会的欢乐,数字三角形等;背包问题:01背包问题原创 2015-04-27 00:39:04 · 6617 阅读 · 2 评论 -
算法学习 - STL的排序函数(sort)使用
排序函数sort()这个函数是STL自带的,功能很强大~ 这里教下使用方法。sort()有三个参数,第一个是排序的起始位置,第二个是排序的结束位置,第三个是排序的判断函数。函数原型为:sort(, <#_RandomAccessIterator __last#>, )这个就是原型了~使用方法首先假设我们有一个vector vec;向量容器,存放了很多无序正数原创 2015-01-03 01:25:25 · 2482 阅读 · 0 评论 -
算法基础 - 查找两个有序数组的中位数
问题描述问题很简单,就是在两个有序的整数数组里(数组A长度为m, 数组B长度为n),找到两个数组合并后的中位数。中位数中位数就是在一个有序数组中,位于中间的数字,假如数组元素个数为偶数,则取两个中间数字的平均数。 例: 1,2,3,4,5 中位数为:3 1,2,3,4 的中位数为:2.5算法讲解这个问题其实看起来挺简单的,网上的一些博客里说的,很多都是一个大致思想,细节有误,代码原创 2015-11-13 02:07:05 · 4675 阅读 · 2 评论 -
算法学习 - 查找第K大的数字
寻找第K大的数字一般我们会找最大的数字和最小的数字,然而时间都是O(N)级别的。这里第K大的数字查找方法其实很简单,就是每次把数组分成两部分,然后看第K大的数字属于哪个组,就查找这个组,扔另一组。这个方法更像快速排序,因为快速排序的时间复杂度是O(NlogN),而这个方法因为不需要对抛弃的一半进行操作,所以这个方法要比NlogN的方法要更快一点,平均复杂度接近O(n)。代码如下://// mai原创 2015-10-24 20:53:31 · 1242 阅读 · 0 评论 -
算法学习 - 最小栈的实现O(1)时间
最小栈最小栈其实和栈没有什么区别的,唯一的区别在于最小栈是可以在O(1)时间内得到当前的栈空间里,最小的值是多少。最小栈的操作最小栈的操作和普通栈的操作没有太大区别,唯一多了一个方法就是getMin()方法,这个方法是用来获取当前栈内的最小值。其他方法就是Push(), Pop(), Top()...等在O(n)时间内找到新的最小值这里就厉害了,先说普通的O(n)的方法~得到栈...原创 2014-12-05 03:56:24 · 9215 阅读 · 9 评论 -
算法学习 - 最长公共子序列(LCS)C++实现
最长公共子序列最长公共子序列的问题很简单,就是在两个字符串中找到最长的子序列,这里明确两个含义: 子串:表示连续的一串字符 。 子序列:表示不连续的一串字符。 所以这里要查找的是不连续的最长子序列,动态规划这里为什么要使用动态规划可以说一下,简单来说动态规划是为了降低时间复杂度的一种算法,申请一个额外空间,来保存每一个步骤的结果,最后从这些结果中找到最优的解。这里有个问题就是:原创 2015-08-25 23:30:22 · 18722 阅读 · 0 评论 -
算法学习 - 图的深度优先遍历(DFS) (C++)
深度优先遍历在图的遍历中,其中深度优先遍历和广度优先遍历是最常见,也最简单的两种遍历方法。深度优先遍历的思想就是一直向下找,找到尽头之后再去其他分支查找。在上一篇博客中我已经写了广度优先遍历(BFS)。 想看的传送门:图的广度优先遍历代码实现这里实现和BFS的差别在于,在BFS中,我们使用的容器是队列(queue),是先进先出的, 而在DFS中我们需要使用的是栈(stack)一个先进后出的容器。其原创 2015-04-01 15:48:26 · 11939 阅读 · 0 评论 -
算法学习 - bitmap实现(c++)
BitMap介绍这里的BitMap指的是把数据存放在一个以bit为单位的数据结构里。 每位都只有0和1两个值。为0的时候,证明值不存在,为1的时候说明存在。举例来说: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]这是24位,也就是24bit, 同时8bit为1个字节。这里的空间也就是3个字节。这个时候假如我们要存放2 4 6 8 9 10原创 2015-03-24 21:47:24 · 6206 阅读 · 1 评论 -
算法学习 - 图的广度优先遍历(BFS) (C++)
广度优先遍历广度优先遍历是非常常见和普遍的一种图的遍历方法了,除了BFS还有DFS也就是深度优先遍历方法,我在我下一篇博客里面会写。遍历过程相信每个看这篇博客的人,都能看懂邻接链表存储图。 不懂的人,请先学下图的存储方法。在我的之前博客里。 传送门:图表示方法然后我们假设有一个图如下: 节点1->3->NULL 节点2->NULL 节点3->2->4->NULL 节点4->原创 2015-04-01 02:25:52 · 11614 阅读 · 0 评论 -
算法学习 - 选择排序的稳定性讨论(C++实现)
选择排序选择排序的思想很简单。 每次选择当前的最小数字。 向后移动一位,选择第二小的数字。 … 移动到倒数第二位,操作后截止。 还不懂的附上百度百科选择排序。稳定性所以到底是不是稳定的呢?不稳定解释看过上面百度百科链接的人就会觉得一定不是稳定的啊。因为例如如下: [5 8 5 2 9 4]这个在第一次选择最小的时候,就把5和2的位置掉换了,变成如下: [2 8原创 2015-04-03 02:51:11 · 3865 阅读 · 2 评论 -
算法学习 - 递归与非递归,位运算与乘除法速度比较
递归调用非递归调用运行时间比较结论位运算与乘除法结论递归调用/非递归调用我们都知道,很多算法,都是用递归实现的。当然它们同时也是可以用非递归来实现。一般我们在对二叉树进行遍历的时候,还有求斐波那契数的时候,递归是非常简单的。代码容易懂,好实现。但是递归的时候,有一个问题,就是需要压栈。为什么要压栈呢?因为当我在函数内部调用自身的时候,要中断当前的操作继续跳转到下一次的实现,而当前运行的状态要原创 2015-03-28 21:10:40 · 4700 阅读 · 1 评论 -
算法基础 - 线段树
线段树线段树本身是一个很简单的数据结构,但是因为应用场景不同,所以每个人设计的节点和结构还有存储方式也都不一样。这造成了结构本身很简单,但是想要学却比较麻烦,先说下存储方式:树存储方式数组树节点指针 我这里只实现了用树节点指针的方式,数组方式同树节点指针一样,只不过leftchild和rightchild做了下标映射。注意数组越界。应用场景给定一堆数字,找在这个区间里有多少个数字给定一堆原创 2016-05-01 02:50:42 · 950 阅读 · 0 评论 -
算法基础 - 并查集
并查集在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时原创 2016-05-13 20:55:03 · 704 阅读 · 0 评论 -
Leetcode - Merge K sorted list
在归并排序中,一般使用的是二路归并排序,而在二路归并的时候,每次比较,找到最小的数字都是O(1)的操作,而在归并K个路得时候,也就是K路归并,会出现一个问题,每次找到最小的数字是一个 O(k)的操作。那么能不能简化这个操作呢?可以的,因为我们要归并的是K个链表,所以头结点的位置变化,并不会导致节点后面的信息丢失。所以要先对K个头结点进行排序,然后把最小的删掉,再排序,那么这种情况最适合的就是堆排序了原创 2016-05-03 21:16:34 · 497 阅读 · 0 评论 -
算法基础 - 2-sat问题
2-SAT问题这个问题其实我们平时早就遇到过,只是从来没有认真的去思考这个问题的解法。这个在我们理解的时候,一般都是按照一个点开始,可以就继续,不可以就停止。例子问题例如我们有10个球,每个球都是编号好的,从:1 - 10这10个球,我们要从中拿出5个球,有以下要求: 并且选了1就不能选择3号球,选择了2号就不能选择4号球,选择了5号就不能选择9号。 但是这里面有个规则:{1, 2}不能同时存在原创 2016-05-30 22:03:55 · 10464 阅读 · 1 评论 -
算法学习 - Bloom Filter(布隆过滤器)学习实现(C++实现)
Bloom filter简介Bloom Filter计算方法Bloom Filter优点缺点优点缺点图示说明Bloom filter简介Bloom filter 是由 Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时间效率,被用来检测一个元素是不是集合中的一个成员。如果检测结果为是,该元素不一定在集合中;但如果检测结果为否,该元素一定不在集合中。因此原创 2015-03-25 02:07:13 · 8246 阅读 · 10 评论 -
算法基础 - 素数判定(Miller-Rabin算法)
素数判定素数不需要解释了,那么素数如何判定?最简单的算法,暴力测试,就是最简单的,从2枚举到sqrt(n)sqrt(n)就可以知道是不是素数了。Fermat小定理 费马小定理:对于质数p和任意整数a,有ap≡a(mod p)a^p ≡ a(mod\ p)(同余)。反之,若满足ap≡a(mod p)a^p ≡ a(mod\ p),pp也有很大概率为质数。将两边同时约去一个a,则有a(p−1)原创 2016-06-05 12:54:43 · 6594 阅读 · 1 评论 -
算法基础 - 最近公共祖先(在线算法/离线算法)
最近公共祖先最近公共祖先的问题已经在前面的博客有说过了。要看代码的,本篇博客写的是普通树的最近公共祖先,并不是二叉树,也许有时间我会写一下在线算法思想对树进行dfs(也就是先序遍历),在遍历过程中,记录下遍历的顺序,这里要注意的是,遍历要记录下所有路径,包括节点的第二次访问,或第三次访问。然后这样就是一个数组了。 0 / \ 1 2 /|\ \ 3 4原创 2016-05-19 14:27:57 · 1347 阅读 · 0 评论 -
算法基础 - 单源点最短路径SPFA
SPFA是非常简单的最短路径算法,思想就是从起点开始,进行宽度优先搜索,不断松弛S点到其他相邻点的距离。如果松弛了点B,则把点B放到队列里。假如点B已经在队列里了,就不要放了,判断在不在队列可以用个数组来表示。引用一段hihocoder上的解释: 构造一个队列,最开始队列里只有(S, 0)——表示当前处于点S,从点S到达该点的距离为0,然后每次从队首取出一个节点(i, L)——表示当前处于点i,原创 2016-05-08 02:41:24 · 2638 阅读 · 0 评论 -
算法基础 - 通过前序遍历和中序遍历得到后续遍历
思想思想很简单,前序遍历,第一个节点一定是当前树的根节点,而这个节点在中序遍历中,分割了左右子树。假如前序:root left1 left2 left3 right1 right2中序一定是:left left left root right right虽然left在中序的顺序不能直接通过前序得到,但是一定知道的是,在中序遍历中,root分割了左右子树。然后递归得到左右子树的遍历,就可以得到整个树了原创 2016-05-07 02:34:54 · 4762 阅读 · 1 评论 -
算法学习-KMP(字符串匹配)解释
KMP算法BF算法BF算法就是我们最基本的求解字符串匹配的算法,算法的时间复杂度为O(M*N),空间复杂度为O(1),具体过程如下:串第一次第二次第三次第四次模式串S[i]abcababcabcababcabcababcabcababc匹配串T[j]原创 2014-10-20 15:28:00 · 1245 阅读 · 0 评论 -
算法基础 - RMQ-ST算法(在线算法)
RMQ问题在线算法离线算法ST Sparse Table 算法预处理数据查询区间完成代码如下RMQ问题RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于一个长度N的数组,在多次询问中,每次都以O(1)的时间得到区间[a, b]的最大值或最小值。在线算法说来惭愧,到现在才刚开始清楚说的在线算法和离线算法是什么意思,所谓在线算法就是说原创 2016-05-18 02:23:43 · 2521 阅读 · 0 评论 -
算法基础 - 树的最近公共祖先
最近公共祖先二叉树的最近公共祖先代码实现普通树的最近公共祖先代码实现最近公共祖先树的公共祖先很容易理解:就是到两个点的路径(A,B)上的公共点。 那么最近公共祖先就是公共路径(A, B)上深度最高的公共点。二叉树的最近公共祖先二叉树的公共祖先很简单,就是在先序遍历也就是DFS过程中,记录当前的祖先,放到栈里,在遍历的过程中,不断对栈进行监控,当前遍历的最近公共祖先发生变化之后,对栈进行弹原创 2016-05-17 21:24:19 · 822 阅读 · 0 评论 -
算法基础 - 最长回文子串
回文串今天来说下最长回文串,首先回文串是:abccba或者acbca这种正反读起来都是一样的字符串,有奇偶之分,在于有没有中间单独的这个字符。传统解法传统解法就是从头遍历整个字符串,把每个字符当做是奇数个数回文串的中心节点,或偶数个回文串的左中心节点。然后向左向右遍历,得到最长回文长度,记下来,然后遍历下一个字符。这个解法的时间复杂度是O(n^2) 空间复杂度是O(1)。这里有个问题就是,假如我的字原创 2016-05-06 04:11:18 · 686 阅读 · 0 评论 -
算法基础 - 求有向图的强连通分支(Tarjan算法)
强连通分支如果两个顶点可以相互通达,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。非强连通图有向图的极大强连通子图,称为强连通分量(strongly connected components)。Tarjan算法Tarjan算法是用来求有向图的强连通分量的。求有向图的强连通分量的Tarjan算法是以其发明者Robert Tarjan命原创 2016-05-30 01:51:23 · 9325 阅读 · 2 评论 -
数据结构 - Trie树(字典树)
Trie树也叫单词查找树或者字典树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。树的大致结构如下图所示: 从上到下的节点,公共前缀只保存一次。代码实现//// main.cpp//原创 2016-04-11 15:57:58 · 732 阅读 · 0 评论 -
算法基础 - 最小生成树(Kruscal算法)
最小生成树就是让一个图里,生成一个树状图,任意两个节点只有唯一的路径到达,并且让这个距离最短。Karuscal算法这个算法是相对于Prim算法( 传送门:Prim算法 )的另外一个算法,这个算法主要的应用场景是对于稀疏图非常好用,因为Karuscal算法是根据边来计算的,每次添加一个最短的边。而Prim的每步是添加一个最短的点,类似于Dijkstra算法的步骤。所以Prim的算法是对于稠密的图效果更原创 2016-05-27 17:02:07 · 1608 阅读 · 0 评论 -
算法基础 - 最小生成树(Prim算法)
最小生成树一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边Prim算法普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家沃伊捷原创 2016-05-15 01:55:04 · 771 阅读 · 0 评论 -
算法基础 - 二叉查找树变成有序双向链表
自己今天真是笨死了,这么简单的题目,竟然在当场写代码的时候没有写出来。这里写一下,其实这个题目非常简单,就是一个中序遍历,在中序遍历的时候,更改一下指针指向。自己在面试写的时候太紧张了,就蒙了。。。下面贴一下代码实现:TreeNode* inorderFlatTree(TreeNode * root){ stack<TreeNode *> st; TreeNode * temp =原创 2016-04-26 01:01:36 · 529 阅读 · 0 评论 -
算法学习 - 欧几里得算法(辗转相除法)(c++实现)
欧几里得算法欧几里得算法也叫辗转相除法,是求两个整数最大公约数的算法。当然也可以求最小公倍数。算法实现其实算法的实现原理就是,有整数a b两个,每次求的一个数字r = a % b,然后把b放到a的位置,把r放到b的位置,递归调用。就是gcd(a, b) { return gcd(b, a%b); }这个样子的。结束条件是当 a%b == 0的时候停止。最大公约数//// main.cpp//原创 2015-03-28 00:56:27 · 30040 阅读 · 5 评论 -
算法学习 - 求二叉树的宽度
二叉树的宽度二叉树的宽度定义为整个二叉树各层节点数,其中最大的值为这个二叉树的宽度。所以二叉树的第一层就是1(根节点)。代码实现(C++)代码实现比较简单,树的遍历一般用递归比较方便。//// main.cpp// TreeWidth//// Created by Alps on 15/3/11.// Copyright (c) 2015年 chen. All rights r原创 2015-03-11 18:17:24 · 6778 阅读 · 2 评论 -
算法学习 - 图的创建和打印
图表示之前的博客里已经说过了图的两种表示方法,一个是邻接链表,一个是邻接矩阵的方法。前面适合稀疏图,后面自然就适合稠密图。图创建邻接矩阵邻接矩阵其实就是二维矩阵,在前面的图表示已经简单的说过了,直接建立一个int G[NumVertex][NumVertex]然后直接输入就好了。下面着重讲一下邻接链表的方法。邻接链表表示方法已经说过了,传送门:图表示。下面看下代码:struct Node{原创 2015-03-10 11:08:21 · 3148 阅读 · 0 评论 -
二叉查找树(二叉排序树)创建,插入,删除操作。
二叉排序树二叉排序树是一个基础的树的数据结构。应用非常多。它的特性就是,左孩子小于parent,右孩子大于parent.寻找节点寻找节点就是直接根据数值的大小,从root节点开始遍历,大于当前遍历节点就向它的右子树查找,相反则查找它的左子树。然后返回。查找最大最小节点直接根据root节点,遍历到最右就是最大节点,遍历到最左,就是最小节点。插入节点原创 2014-07-31 22:29:37 · 2905 阅读 · 0 评论 -
算法学习 - Hash Table操作,分离链接法解决哈希冲突
分离链接法hash table是映射机制的,最大的优点就是它的操作是O(1)级别的。但是会出现哈希冲突,这就需要几种办法来解决。这里先说一种:分离链接法。就是当插入的位置已经存在一个值之后,那么在这个值之后插入,就可以了,也叫拉链法。(但是其实会降低查找速度,变成O(n)级别)下面是代码://// main.cpp// HashTable_SeparateCha原创 2014-08-05 21:49:10 · 1557 阅读 · 0 评论 -
算法学习 - 栈的链表实现(C++)
栈是用的很多的一个数据结构,这里写用链表shi原创 2014-07-28 00:54:09 · 961 阅读 · 0 评论