
算法之美
文章平均质量分 62
songuooo
Make easy things easy & hard things possible.
展开
-
关键路径
关键路径与活动的完成有关,总之路径长度最长的路径叫关键路径。在AOE-网中只有一个入度为0的顶点(源点)和只有一个出度为零的顶点(汇点)。图的存储结构为邻接表。算法用到拓扑排序和逆拓扑排序。算法如下:(1) 算法用到的拓扑排序算法void topoOrder(ALGraph *G, int ve[], int instack[]){ int i, v, indeg原创 2012-08-03 15:47:28 · 586 阅读 · 0 评论 -
定位单向链表某个结点
1. 描述输入一个单向链表(可带表头), 输出该链表中倒数第 k 个结点。链表的倒数第 0 个结点为链表的尾指针,即链表的最后一个结点。结点定义如下:typedef struct BiNode { int data; struct BiNode *next;}BiNode;2. 思路在遍历时维持两个指针,第一个指针从链表的头指针开始遍历, 在第 k-1原创 2012-08-17 18:35:25 · 819 阅读 · 0 评论 -
动态规划基础
众所周知,动态规划(Dynamic Programming)常用于解决最优化问题。能采用动态规划的问题具有两个重要的性质:最优子结构和子问题重叠性。下面就温习一下吧。1. 最优子结构(Optimal substructure)如果问题的一个最优解中包含了子问题的最优解,即原问题的最优解可以通过子问题的最优解构造,或者说可以利用子问题的最优解来构造原问题的一个最优解,则问题具有最优子原创 2012-08-19 19:35:58 · 687 阅读 · 0 评论 -
装配线调度(动态规划)
1. 问题描述公司在有两条装配线的工厂内生产汽车,如下图所示。一个汽车底盘在进入每一条装配线后,在一些装配站中会在底盘上安装部件,然后完成的汽车在装配站的末端离开。每一条装配线上有n个装配站,编号为j=1,2...n。装配线i(i=1,2)的第j个装配站表示为Sij。装配线1的第j个站和装配线2的第j个站执行相同的功能。然而这些装配站是在不同的时间建造的,并且采用了不同的技术,一次每个站上所需原创 2012-08-20 16:38:20 · 1377 阅读 · 1 评论 -
n 个数中最小的 k 个数
1. 描述输入 n 个整数,输出其中最小的 k 个。2. 解法一般的方法是用选择排序,直到k个最小的数产生。时间复杂度为O(nk),空间复杂度为O(n)。或者是对这n个数用快速排序从小到大排好序后,输出前k个数,时间复杂度为O(nlogn),空间复杂度为O(n)。但若数据量非常庞大,以至于整个内存空间都放不下,上面两种方法就无能为力了。利用堆排序可以解决原创 2012-08-15 20:45:19 · 1958 阅读 · 0 评论 -
字符串的排列与组合
求字符串的排列和组合是递归很典型的应用,是很好的考查对递归理解程度的一类问题。下面的求字符串的排列、组合的算法全部用递归实现。1. 字符串的排列(1) 描述输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串 abc,则输出由字符 a、b、c 所能排列出来的所有字符串 abc、acb、bac、bca、cab 和 cba。(2) 字符串中没有重复字符先不考虑原创 2012-08-21 22:12:18 · 786 阅读 · 0 评论 -
矩阵链乘法(动态规划)
1. 描述给定由n个要相乘的矩阵构成的序列,要计算乘积 A1A2...An 矩阵的乘法满足结合率,然而不同的结合虽然运算结果一样,但需要运算的次数是不相同的,例如:设3个矩阵的维数分别为10x100,100x5,5x50。如果按((A1A2)A3)的次序相乘,共要做10x100x5原创 2012-08-24 19:10:05 · 1280 阅读 · 0 评论 -
输出0到最大的n位数
1. 描述输入数字 n,按顺序输出从 0 最大的 n 位 10 进制数。比如输入 3,则输出 0、1、2、3 一直到最大的 3位数,即 999。2. 思路方法一,求出最大的n位数(10^3 - 1),然后由一个循环控制输出。方法二,当n很大时,方法一不再适用,此时可用字符串模拟数字运算,代码较长。方法三,由字符串的排列和组合>的递归算法得到启示,可以利用递归求解。原创 2012-08-28 11:11:38 · 1323 阅读 · 0 评论 -
最优二叉查找树(动态规划)
1. 描述给定一个有序序列K={k12. 分析(1)最优子结构一个最优二叉树的子树必定包含连续范围的关键字ki~kj,1 如果一棵最优二叉查找树T有一棵含有关键字ki~kj的子树T',那么,T'也是一棵最优查找树,这通过剪贴思想可以证明。构造最优子结构:在ki~kj中,选定一个r,i (2)递推公式定义e[i,j]为一棵包含关键字ki~kj的最优二叉树的期望原创 2012-09-08 21:56:59 · 1571 阅读 · 0 评论 -
点分直线,直线分平面,平面分空间
如下表所示:x0123456789nx个点最多能把直线分割成多少部分A12345原创 2012-09-11 12:11:28 · 767 阅读 · 0 评论 -
最长公共子序列LCS(动态规划)
1. 描述给定两个序列X = { x1 , x2 , ... , xm },Y = { y1 , y2 , ... , yn }求X和Y的一个最长公共子序列。2. 分析设最长子序列 Z = { z1 , ... , zk }则1、若 xm = yn , 则 zk = xm = yn,且Z[k-1] 是 X[m-1] 和 Y[n-1] 的最长公共子序列;2原创 2012-09-01 22:51:44 · 832 阅读 · 0 评论 -
筛选素数
筛选素数:打印出1, 2, 3, ..., n中所有的素数。“筛子法”:2是第一个素数,保留下来,筛掉所有的2的倍数;3被保留下来,则3是素数,筛掉所有的3的倍数;...直至筛选完毕。代码如下:void prime(int n){ int num[n + 1]; int i, j; for (i = 2; i <= n; i++) num[i] = 1;原创 2012-09-14 22:21:54 · 525 阅读 · 0 评论 -
数组循环移位
问题描述:n个元素存储于数组A[0..n-1]中,求向右或向左循环移位 k (k >= 0)位得到的新数组A[]。1. 循环右移步骤:(1) k = k % n;(2) 把序列分成前(n-k)个数和后k个数两组分别进行逆转操作,如下图:代码如下:void rightShift(char A[], int n, int k){ k = k原创 2012-08-08 16:07:12 · 421 阅读 · 0 评论 -
O(1)时间求出栈中最小的元素
1. 描述定义栈的数据结构,要求添加一个 min 函数,能够得到栈的最小元素。要求函数 min、push 以及pop 的时间复杂度都是O(1)。这是2010年Google的一道面试题。2. 求解思路是这样的, 定义另外一个辅助栈,不妨叫MinStack,栈中存放数据栈(不妨叫Stack)中当前最小元素在数据栈中的标号。当向数据栈中push 元素(不妨叫ele)的时候:若原创 2012-08-12 21:32:32 · 1763 阅读 · 0 评论 -
最小生成树
普里姆(Prime)算法和克鲁斯卡尔(Kruskal)算法是两个利用最小生成树(MST)性质构造最小生成树的经典算法。下面是普里姆算法构造最小生成树。图的存储结果采用邻接矩阵。1. MST性质假设N = (V, {E})是一个连通网,U是顶点集V的一个非空子集。若(u, v)是一条具有最小权值(代价)的边,其中u∈U,v∈V-U,则比存在一条包含边(u, v)的最小生成树。原创 2012-08-03 16:22:26 · 553 阅读 · 0 评论 -
最短路径
1. 问题描述单源点最短路径:给定带权有向图G和源点v,求从v到G中其余各顶点的最短路径。2. 迪杰斯特拉(Dijkstra)算法迪杰斯特拉算法按照最短路径递增的次序产生最短路径。具体参见数据结构。3. 算法实现采用邻接矩阵作为其存储结构。void dijkstra(MGraph *G, int v0, int (*P)[G->vexnum], int D[原创 2012-08-03 16:48:38 · 445 阅读 · 0 评论 -
KMP字符串匹配算法
KMP算法是一种改进的字符串匹配算法。KMP算法的关键是根据给定的模式串sub,定义一个next函数。next函数包含了模式串本身局部匹配的信息。1. 算法实现(1) 计算next函数算法如下void getNext(char sub[], int next[]) { int i = -1, j= 0, len = strlen(sub);原创 2012-08-03 18:23:53 · 748 阅读 · 0 评论 -
一整数是否为2的方幂
位操作又有用武之地了。代码如下:int isPower(long n){ if (n > 0 && (n & (n - 1)) == 0) return 1; //n是2的方幂 return 0; //n不是2的方幂}原创 2012-08-04 16:45:17 · 1504 阅读 · 0 评论 -
顶点着色问题应用
1. n个学生对m个宣讲会中的若干个感兴趣,如何安排宣讲会的时间(每个宣讲会持续的时间相同),使得每个学生对自己感兴趣的宣讲会时间不冲突,且宣讲会的总时间最短?此问题可以转化成顶点着色问题。把每个宣讲会看作是一些散布的点,对于每个学生,把他感兴趣的宣讲会之间两两相连,如:学生A希望参加宣讲会1、2、3学生B希望参加宣讲会1、3、4 则: 设宣讲会1原创 2012-08-04 16:24:22 · 8656 阅读 · 0 评论 -
N!中末尾0的个数
N!中末尾0的个数等于N!质因数分解N! = 2^a X 3^b X 5^c X ...中幂项5^c的指数c。代码如下:int count(int N){ int result = 0; while(N) { result += N / 5; N /= 5; } return result;}原创 2012-08-04 16:39:59 · 722 阅读 · 0 评论 -
寻找另一半
最早遇到这个问题实在的试题中,当时没有找到好的解决方法,后来在中遇到了同样的问题。问题是这样的:有n个ID,其中有个ID出现的次数超过了总数的一半,求此ID。如果不考虑算法的时间复杂度,几乎没有人会解不出这个问题。但如果ID的个数是海量的,几十MB,几百MB甚至有数GB,那么不考虑时间复杂度是不能忍受的。下面是高效解决此问题的思路:每次删除两个不同的ID,最后剩原创 2012-08-04 18:49:05 · 424 阅读 · 0 评论 -
二进制中1的个数
位运算操作不能小看它哦。设二进制的位数为m, 1的个数为n。1.时间复杂度为O(m)的算法int count(long b){ int n; for (n = 0;b;b >>= 1) if (b & 1) n++; return n;}2. 时间复杂度为O(n)的算法int count2(long b){ int原创 2012-08-04 16:33:00 · 407 阅读 · 0 评论 -
少一个数的子序列的最大乘积
问题描述:n个数组成的一个序列,求任意(n - 1)个数的组合中乘积最大的一组,规定不能用除法。这个问题来自。这n个数存于数组A[0..n-1]中。1 解法一 设s[i]为数组A[]中前i个数的乘积,即s[i] = 1 i = 0时,s[i] = s[i - 1] * A[i] i = 1,2,...,n设t[i]为数原创 2012-08-04 20:38:45 · 810 阅读 · 0 评论 -
最大连续子序列之和(动态规划)
1. 问题描述设n个元素的序列存储在数组A[0..n-1]中,求数组中连续子序列之和的最大值。2. 递推公式设All[i]为子问题A[i..n-1]的连续子序列之和的最大值,start[i]为从A[i]开始的连续序列之和的最大值,因此:All[i] = A[n-1] i = n - 1时,All[i] = max{All[i + 1], start[i]}i = 0原创 2012-08-08 14:43:59 · 3168 阅读 · 1 评论 -
最长递增子序列(动态规划)
1. 问题描述设n个元素的序列存储在数组A[0..n-1]中,求序列中最长递增子序列(不要求连续)的长度。2. 递推公式设LIS[i]为序列A[0..i]中最长递增子序列的长度。则:LIS[i] = 1 i = 0,LIS[i] = max{1, LIS[k] + 1}A[i] > A[k]且0代码如下:int maxLIS(int A[], int n原创 2012-08-08 15:01:00 · 748 阅读 · 0 评论 -
给定1到N的随机数函数,产生1到M的随机数
给定能随机生成整数 1 到 n 的函数,写出能随机生成整数 1 到 m 的函数(m > n)。设 n = 5, m = 7关键是让生成的 1 到 7 的数出现概率相同。调用 n 次给定函数,生成 n 个 1 到 5之间的随机数,选取最大数所在位置,直到剩下最后一个。如:初始的 7 个数 [1, 2, 3, 4, 5, 6, 7]。(1)7 个 1 到 5 的随机数,如 [5,原创 2012-09-16 17:09:09 · 5069 阅读 · 3 评论