DS & Algorithm
文章平均质量分 64
eriol
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
RMQ
RMQ英文是Range Maximum(Minimum) Query,是用来求某个区间的最大值/最小值,通常用在查询次数比较大的区间最值问题中。 RMQ的原理是动态规划,利用了倍增的思想。我们用A[1...N]表示一组数,[Li,Ri]表示题目涉及到的查询区间。 设F[i,j]表示从A[i]到A[i + (2^j) - 1]这个范围的最大值,也就是以A[i]为起点的连续2^j个数的最大值。由于...原创 2011-09-12 21:50:20 · 173 阅读 · 0 评论 -
一些和图论有关的算法
1. 拓扑排序 算法:首先对每个顶点计算它的入度。然后,将所有入度为0的顶点放到一个初始为空的队列(或栈)中。当队列不空时,删除一个顶点v,并将与v邻接的所有顶点的入度均减1。只要一个顶点的入度降为0,就把该顶点放入队列中。此时,拓扑排序就是顶点出队的顺序。使用邻接表的情况下,该算法时间复杂度为O(|E|+|V|)。 public void topsort() throws CycleF...2011-07-17 19:10:05 · 256 阅读 · 0 评论 -
最长公共子序列
题目 如果字符串1中的所有字符都按顺序的出现在字符串2中,那么称字符串1是字符串2的子串。现在给定两个字符串,求它们的最长公共子串。 例如:对于字符串BDCABA和ABCBDAB,字符串BCBA和BDAB都是是它们的最长公共子串,长度为4。 思路 考虑字符串X = {x1, x2, ... xm} 和 Y = {y1, y2, ... yn},记 Z = {...原创 2011-10-09 18:15:28 · 211 阅读 · 0 评论 -
弗洛伊德算法
Floyd-Warshall算法,简称Floyd算法,用于求解任意两点间的最短距离,时间复杂度为O(n^3)。 使用条件&范围 通常可以在任何图中使用,包括有向图、带负权边的图。 Floyd-Warshall 算法用来找出每对点之间的最短距离。它需要用邻接矩阵来储存边,这个算法通过考虑最佳子路径来得到最佳路径。 算法思想 // dist(i,j...原创 2011-10-07 20:38:33 · 347 阅读 · 0 评论 -
最大栈和最大队列
最大栈 具有栈的功能,并且提供O(1)的时间复杂度来获取最大值max。 思路:使用一个辅助栈assist来维护最大值,最大值为assist的栈顶元素。当入栈的值大于最大值时,将该值压入assist栈,相当于更新了最大值。当有元素出栈时,检查该元素是否为最大值,如果是,则assist出栈,即更新了最大值。 import java.util.Stack; publi...2011-10-04 20:50:44 · 288 阅读 · 0 评论 -
楼层扔鸡蛋问题
有限层数和蛋数,求即使最坏情况下需要的最少判断次数 两个软硬程度一样但未知的鸡蛋,它们有可能都在一楼就摔碎,也可能从一百层楼摔下来没事。有座100层的建筑,要你用这两个鸡蛋确定哪一层是鸡蛋可以安全落下的最高位置。可以摔碎两个鸡蛋。 这是典型的动态规划问题。假设f[n]表示从n层楼找到摔鸡蛋不碎安全位置的最少判断次数。假设第一个鸡蛋第一次从第i层扔下,如果碎了,就剩一个鸡蛋,为确定...原创 2011-10-03 13:44:02 · 227 阅读 · 0 评论 -
判断两个链表是否相交
题目 : 给出两个链表的头指针,比如h1,h2,判断这两个链表是否相交。 扩展: (1) 如果链表可能有环呢? (2) 如何求出两个相交链表的相交的第一个节点。 如果链表没有环 假设两个链表没有环,如果它们相交,那么它们的最后一个元素必定相同。 public boolean isConNLoop(ListNode h1, ListNode h2) ...2011-10-02 15:44:10 · 153 阅读 · 0 评论 -
求和为n的连续正整数序列
题目:输入一个正数n,输出所有和为n连续正整数序列。 例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-5、4-6和7-8。 解法1 因为整数序列是有序的,可以设立两个游标begin和end,通过判区间[begin,end]的和是否为N来得到这个序列。如果区间和大于n,begin往前移动,如果小于n,end往前移动...原创 2011-09-27 18:49:10 · 480 阅读 · 0 评论 -
并查集
1. 概述 并查集(Disjoint set或者Union-find set)是一种树型的数据结构,常用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。 2. 基本操作 并查集是一种非常简单的数据结构,它主要涉及两个基本操作,分别为: 合并两个不相交集合。 判断两个元素是否属于同一个集合。 (1) 合并两个不相交集合(Union(x,y)) ...原创 2011-09-25 22:07:14 · 248 阅读 · 0 评论 -
几个经典算法的概念
动态规划(Dynamic Programming) 一、动态规划的基本思想: 动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解...原创 2011-06-11 18:13:54 · 178 阅读 · 0 评论 -
映射二分堆
引入 平常,我们用堆最常见的就是随机地加入元素,随机地取最大值或最小值。这些基本的操作C++中的priority_queue和set都能很好的完成,而且C++中还有一个make_heap,效率较前面2个会更高。而且前面提到的STL都是采用红黑树实现的,很具有稳定性。 上面的堆虽然使用简单,但功能上还是有些局限。比如前面提到的堆都只能实现删除最值并没有办法删除指定的值。而且一般...原创 2011-09-18 20:57:52 · 282 阅读 · 0 评论 -
在两个有序数组中找第N数
给定两个有序的数组,长度分别为m和n,求这两个数组中的第K个元素。 问题分析: 1. 把 A 平均分为前后两个部分,前部分有 x 个元素,后部分有 n-x 个元素(由于 A 是有序的,所以后一部分的所有元素都大于前一部分)。A[x] 为 A 的后一部分中的第一个元素。 2. 同理把 B 也平均分成前后两个部分,前部分有 y 个元素,后部分有 m-y 个元素。B[y] ...原创 2011-09-14 22:32:00 · 555 阅读 · 0 评论 -
寻找树形图中的最长路径
题目: 在一个迷宫中找距离最长的两个点。 迷宫可以看作是一个无根树,因此,这个问题等价与在一个树形图中找最远的两个节点,也叫做这个图的直径。 迷宫、树形图有个很好的特点:即任意两个节点之间的距离就是这两点之间的最短路径和最长路径,也可以说任意两个节点之间的距离一定的。 其算法为: 任选一点u为起点,对树进行BFS遍历,找出离u最远的点v。然后以v为起点,再进行BFS遍历...原创 2011-09-14 16:06:44 · 1324 阅读 · 0 评论 -
复制链表
题目:已知一链表,每个节点除了有一个指向下一节点的指针外,还有一随机指针指向链表中的任意节点(可能为空,也有可能为自身),请复制一个链表,要求节点的顺序以及节点上的随机指针指向的节点位置和原链表一致。 这个题目有个很巧妙的解法,可以达到O(n)的效率,其中心思想是把原始链表和复制链表先合并为一个有固定顺序的链表,然后给复制链表中每个节点的随机指针复制,最后再打断链表恢复原样...原创 2011-09-13 22:52:07 · 424 阅读 · 0 评论 -
二分查找数组中的转折点
有一个有序的数组,将其中的元素都右移X位,这样将该数组变成了一个部分有序的数组。位置0到X以及X+1到n-1是有序的,但是array[X] > array[X+1]。array[X+1]为原先数组的最小值,我们称其为转折点。请找出该X+1。 解题思路:使用二分查找的方法来搜索X+1,时间复杂度为O(logn)。考虑只有一个元素和数组仍然保持有序的特殊情况。 public...2011-09-13 16:27:45 · 931 阅读 · 0 评论 -
树的非递归先序遍历
对于树的遍历操作,通常使用递归的方式写起来比较简单。但是偶尔也可以尝试一下非递归的写法。 public void preOrder(Node t) { if (t == null) return; Stack<Node> stack = new Stack<Node>(); Stack<Node&g...原创 2011-09-12 22:08:21 · 170 阅读 · 0 评论 -
拓扑排序
拓扑排序是对依赖关系的排序,使得如果A必须在B前发生,则A的顺序在B的前面。一般我们使用有向无回路图(DAG)来说明事件发生的先后次序。对这种有向无回路图的拓扑排序的结果为该图所有顶点的一个线性序列,满足如果G包含(u,v),则在序列中u出现在v之前(如果图是有回路的就不可能存在这样的线性序列)。这样,一个图的拓扑排序可以看成是图的所有顶点沿水平线排成的一个序列,使得所有的有向边均从左指向右...原创 2011-01-04 14:20:52 · 134 阅读 · 0 评论 -
二叉树中两个节点的最近公共祖先
求二叉树中任意两个节点的最近公共祖先也称为LCA问题(Lowest Common Ancestor)。 二叉查找树 如果该二叉树是二叉查找树,那么求解LCA十分简单。 基本思想为:从树根开始,该节点的值为t,如果t大于t1和t2,说明t1和t2都位于t的左侧,所以它们的共同祖先必定在t的左子树中,从t.left开始搜索;如果t小于t1和t2,说明t1和t2都位于t的...原创 2011-09-12 21:42:57 · 527 阅读 · 0 评论 -
括号匹配问题
括号匹配问题: import java.util.Stack; public class SymbolMatch { public boolean check(String str) { Stack<Character> s = new Stack<Character>(); boolean match = true; for (i...2011-09-06 11:54:27 · 140 阅读 · 0 评论 -
Trie树
Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,例如,英文字母的字典树是一个26叉树,数字的字典树是一个10叉树。 Trie的核心思想是用空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。当然,如果系统中存在大量字符串且这些字符串基本没有公共前缀,则相应的trie树将非常消耗内存,这也是trie树的一个缺点。 Trie树的...原创 2011-09-05 21:40:24 · 159 阅读 · 0 评论 -
链表逆序
链表逆序,即将原先的链表 a->b->c->d, 变为 d->c->b->a。需要使用三个指针来进行操作。 public int* reverse(int* head) { int* front = head; int* back = null; int* temp; while (front != null) { te...原创 2011-09-03 00:02:45 · 184 阅读 · 0 评论 -
海量数据面试题
1. 给定a、b两个文件,各存放50亿个url,每个url各占用64字节,内存限制是4G,如何找出a、b文件共同的url? 两个50亿个url的文件,大概有50 0000 0000 * 64 B = 640G的大小,肯定不能全部读入内存,可以分组解决。准备1030个桶,读取两个文件的url,对每个url,通过hash(url)%1031, 把url映射到其中一个桶,然后把每个桶的u...原创 2011-08-28 14:44:22 · 133 阅读 · 0 评论 -
二叉树的前中后序遍历
题目:给出二叉树的前序遍历和中序遍历,求后序遍历。 背景知识:前序、中序和后序遍历指的是父节点的遍历顺序。 例如前序为父节点->左子树->右子树,中序为左子树->父节点->右子树,后序为左子树->右子树->父节点 解题思路: 1. 前序的第一个元素为根节点 2. 在中序以根节点划分为左右两个子树 3. 前序中先出现的元素为该子树中的父节点 4. 左...2011-01-09 20:24:25 · 134 阅读 · 0 评论 -
前缀和后缀表达式
前缀表达式:也被称为波兰表示法,其特点是将操作符置于操作数之前。 中缀表达式:即我们常用的表示方法。 后缀表达式:又被称为逆波兰法,其特点是将操作符置于操作数之后。 例子: 前缀表达式:*/b-cad 中缀表达式:(c-a)/b*d 后缀表达式:ca-b/d* 解析前缀表达式:找到最右边的操作符(即最先运算的操作符),取其右边的两个操作数进行运算,然后找右边第二个操作符,以此类推。 ...原创 2011-01-08 22:59:30 · 250 阅读 · 0 评论 -
反转字符串的优化方法
思路: 对变量交换进行优化,不适用额外的中间变量。 解法一:使用异或操作 char* strrev1(const char* str) { char* tmp = new char[strlen(str) + 1]; strcpy(tmp,str); char* ret = tmp; char* p = tmp + ...原创 2011-01-04 14:44:32 · 238 阅读 · 0 评论 -
单向链表操作总结
1. 有可能会改变链表第一个元素的任何子函数都必须把一个指针传递给头指针。 2. 在遍历链表的时候,千万不要忘记检查自己是否已经到达了它的末尾。 3. 如果要在单向链表中删除或插入一个元素,就必须知道指向删除点或插入点前面那个元素的指针才行。 4. 单向链表的元素删除操作至少要使用两个指针才能正确完成。事实上,单向链表的元素插入操作也需要两个指针才能正确完成,...原创 2011-01-04 14:42:04 · 243 阅读 · 0 评论 -
单向链表中的一些算法
1. 在一个单向链表中,寻找链表中间节点。 使用两个指针,快指针每次步进为2,慢指针每次步进为1。当快指针到达链表尾部时,慢指针指向的就是链表的中间。 Node findMiddleNode(Node head) { if (head == null) return head; Node p1 = head; Node p2 =...2011-01-04 14:36:46 · 148 阅读 · 0 评论 -
求最长单调递减子序列
问题描述:给出一个数列,找出其中最长的单调递减(或递增)子序列。 解题思路:动态规划。假设0到i-1这段数列的最长递减序列的长度为s,且这些序列们的末尾值中的最大值是t。对于a[i]有一下情况: (1) 如果a[i]比t小,那么将a[i]加入任何一个子序列都会使0到i的最长单调序列长度变成s+1,这样的话,在0到i的数列中,长度为s+1的递减子序列的末尾值最大值就是a[i]; (...原创 2011-01-04 14:33:03 · 379 阅读 · 0 评论 -
nlogn求逆序对
问题描述:若一个数组为[A1, A2, ..., An],若有i<j且Aj>Ai,那么Ai和Aj就构成一个逆序对。该问题是求出数组中所有逆序对的数目。 算法思想:使用分治法可以在O(nlogn)的时间复杂度下,求出逆序对。其思想为,把一个数组拆分为两个子数组,不妨称为L和R,那么原数组的逆序对数就等于L的逆序对数加上R的逆序对数,再加上一个元素在L中另一个元素在R中构成的...原创 2011-01-04 14:29:36 · 449 阅读 · 0 评论 -
求连续子序列的最大值
问题描述: 有一串数字(可正可负的int,放在数组Num里),要求找到起始位置start和终止位置end,使得从start位置到end位置的所有数字之和最大,返回这个最大值max。 算法思想:使用动态规划。 设 f[x] 为以 a[x] 终止且包含 a[x] 的最大序列的和,有: f[1] = a[1]; f[x+1] = f[x] > 0 ? f[x] +...原创 2011-01-04 14:27:41 · 245 阅读 · 0 评论 -
求字符串的全排列
问题描述:求一个序列的所有排列情况。 算法思路:使用递归的思想。将每个元素放到长度为n的序列的第一个,然后对剩余的元素进行全排列。 参数说明:in表示输入的字符串,out用来存放输出的字符串,length表示字符串长度,used用来标记哪些字符已经被使用,level用来表示递归的深度。注意,当递归返回时,要将used相应项恢复。 void permute(char[] in, char...原创 2011-01-04 14:26:18 · 121 阅读 · 0 评论 -
洗牌算法
问题描述:给出洗牌的一个算法,并将洗好的牌存储在一个整形数组里。 算法思想:原地排列给定的数列,在第i次迭代时,元素A[i]是从A[i]到A[n]中随机选取的,第i次迭代后,A[i]保持不变。时间复杂度为O(n)。该程序将会产生n*(n-1)*(n-2)*...*1种等可能的情况,它们正好与1至n的n!种排列一一对应。 void shuffle(int[] a) { ...原创 2011-01-04 14:22:41 · 111 阅读 · 0 评论
分享