随笔分类 -  算法导论习题解答

算法导论 18-2 连接与分裂2-3-4树
摘要:CLRS 18-2连接与分裂2-3-4树 连接操作的输入为两个动态集合S'和S'',以及一个元素x,使得对任何x'ε S',x'' ε S'',有key[x'] < key[x] < key[x'']。它返回一个集合S = S' U {x} U S''。分裂操作有点像一个“逆”操作:给定一个动态集S和一个元素xε S,它创建一个集合S',其中包含了S - {x}中所有关键字小于key[x]的元素;同时创建了一个集合S'',其中包含了S - 阅读全文

posted @ 2012-07-06 15:23 NULL00 阅读(2407) 评论(0) 推荐(0)

算法导论16.2-2 0-1背包问题
摘要:CLRS 16.2-2 请给出一个解决0-1背包问题的运行时间为O(nW)的动态规划方法,其中,n为物品的件数,W为窃贼可放入他的背包中的物品中的最大重量。我们有n种物品,物品j的重量为wj,价格为pj。我们假定所有物品的重量和价格都是非负的。背包所能承受的最大重量为W。如果限定每种物品只能选择0个或1个,则问题称为0-1背包问题。可以用公式表示为:maximize subject to 方法一:采用最原始的递归方法,公式为V(1,...,n) = max(vk + V(1,...,k-1,k+1,...,n));时间复杂度为O(2n),很多子问题被重复计算。View Code 1 #i... 阅读全文

posted @ 2012-05-18 15:22 NULL00 阅读(5388) 评论(2) 推荐(0)

算法导论16.1-3 区间图着色(interval-graph coloring)问题(贪心算法)
摘要:CLRS 16.1-3假设要用很多个教室对一组活动进行调度。我们希望使用尽可能少的教室来调度所有的活动。请给出一个有效的贪心算法,来确定哪一个活动应使用哪一个教室。(这个问题也被成为区间图着色(interval-graph coloring)问题。我们可作出一个区间图,其顶点为已知的活动,其边连接着不兼容的活动。为使任两个相邻结点的颜色均不相同,所需的最少颜色对应于找出调度给定的所有活动所需的最少教室数。)方法一:我们很容易就可以想到用P227页的GREEDY-ACTIVITY-SELECTOR(s, f)来解决这个问题,首先调用这个函数,得到可以兼容的最大活动数,然后再在余下的活动中再次调用 阅读全文

posted @ 2012-05-15 15:11 NULL00 阅读(10487) 评论(4) 推荐(3)

算法导论15-1双调欧几里得旅行商问题 & 15-2整齐打印
摘要:CLRS 15-1 双调欧几里得旅行商问题欧几里得旅行商问题是对平面上给定的n个点确定一条连接各点的最短闭合旅程的问题。如图(a)给出了一个7个点问题的解。这个问题的一般形式是NP完全的,故其解需要多于多项式的时间。J. L. Bentley建议通过只考虑双调旅程来简化问题,这种旅程即为从最左点开始,严格地从左到右直至最右点,然后严格地从右到左直至出发点。下图(b)显示了同样的7个点的最短双调路线。在这种情况下,多项式的算法是可能的。事实上,存在确定的最优双调路线的O(n2)时间的算法。描述一个确定最优双调路线的O(n2)时间的算法。可以假设任何两点的x坐标都不相同。(提示:从左到右扫描,保持 阅读全文

posted @ 2012-05-13 12:47 NULL00 阅读(4889) 评论(1) 推荐(0)

算法导论14-2习题解答 Josephus排列(约瑟夫环)
摘要:CLRS 14-2Josephus问题的定义如下:假设n个人排成环形,且有以正整数m<=n。从某个制定的人开始,沿环报数,每遇到第m个人就让其出列,且报数进行下去。这个过程一直进行到所有人都出列为止。每个人出列的次序定义了整数1,2,...,n的(n, m)-Josephus排列。例如,(7,3)-Josephus排列为<3,6,2,7,5,1,4>。a)假设m为整数。请描述一个O(n)时间的算法,使之对给定的整数n,输出(n, m)-Josephus排列。b)假设m不是个常数。请描述一个O(nlgn)时间的算法,使给定的整数n和m,输出(n, m)-Josephus排列。解 阅读全文

posted @ 2012-05-10 14:01 NULL00 阅读(4486) 评论(4) 推荐(0)

算法导论14.1节习题解答
摘要:算法导论习题解答系列停了一年了,现在重新拾起,好多算法已经忘了,有的记得大概,但是真正的用代码实现却很难下手。CLRS 14.1-3 写出OS-SELECT的非递归形式一般递归形式改写为非递归形式要用到while,有时还要用到栈结构。OS-SELECT(x, i){ r = size[left[x]] + 1; while (r != i) { if (i < r) { x = left[x]; r = size[left[x]] + 1; } else { x = right[x]; i = i -r; r... 阅读全文

posted @ 2012-05-08 18:20 NULL00 阅读(5190) 评论(3) 推荐(1)

算法导论13-1节习题解答
摘要:CLRS 13.1-1利用性质画图,略CLRS13.1-2是否CLRS13.1-3是,因为就根部被改变了,并不与其他性质矛盾。CLRS13.1-44,两个子结点都为红色3,两个子结点一红一黑2,两个子结点都为黑树的叶子的深度将会都一样,因为路径上都是黑结点了。CLRS13.1-5略CLRS13.1-6当路径上一半黑一半红时,为最多,2^(2k) - 1个,当路径上全是黑时,为最少,2^k - 1个。CLRS13.1-7最大比值为1,即根部为黑结点,两个孩子为红,然后就是NIL结点(为黑)。最小比值为0,这时全是黑结点。 阅读全文

posted @ 2011-05-04 17:30 NULL00 阅读(1642) 评论(3) 推荐(0)

算法导论12.2节习题解答
摘要:CLRS 12.2-1C错,240及240之后的节点应该都为911左子树上的节点,那么所有节点必然小于或等于911,但点912明显违反了。CLRS12.2-2SEARCH-MINIMUM(x) if(left[x] != NIL) SEARCH-MINIMUM(left[x]) return xSEARCH-MAXIMUM(x) if(right[x] != NIL) SEARCH-MAXIMUM(right[x]) return xCLRS12.2-3TREE-PREDECESSOR(x) if(left[x] != NIL) return TREE-MAXIMUM(left[x]) y = 阅读全文

posted @ 2011-04-21 10:23 NULL00 阅读(1128) 评论(1) 推荐(0)

算法导论12.1-3习题解答(非递归中序遍历)
摘要:CLRS 12.1-3:给出一个非递归的中序树遍历算法。(提示:有两种方法,在较容易的方法中,可以采用栈作为辅助数据结构;在较为复杂的方法中,不采用栈结构,但假设可以测试两个指针是否相等。)算法思想:1.采用栈的话,先寻找最左边的节点,把经过的节点都存入栈中,第一个被弹出来的为最左节点,那么访问其右子树,对右子树也像前面一样遍历,整个流程跟递归一样。2.不采用栈的话,先是访问最左节点,然后访问其右子树,然后回溯到最左节点的父节点,不断重复这个过程,思路还是一样。这里参考了重剑无锋的http://blog.csdn.net/kofsky/archive/2008/09/05/2886453.as 阅读全文

posted @ 2011-04-20 20:43 NULL00 阅读(5983) 评论(3) 推荐(2)

算法导论10.2-7习题解答(单链表逆转)
摘要:CLRS 10.2-7 :在O(n)时间内对给定的单链表进行逆转。解法:这题没什么技巧,就是将指针的指向进行改变即可。#include <iostream>usingnamespace std;//很简单的Node 和 Listclass Node{public: Node* next; int data; Node(); Node(int d);};class List{public: Node* first; List(); void insert(int d);};int main(){ int K =5; List* list =new List(); ... 阅读全文

posted @ 2011-04-16 19:23 NULL00 阅读(851) 评论(1) 推荐(0)

算法导论10.1-7习题解答(用两个队列实现一个栈)
摘要:CLRS 10.1-7 :说明如何用两个队列来实现一个栈,并分析有关栈操作的运行时间。解法:1.有两个队列q1和q2,先往q1内插入a,b,c,这做的都是栈的push操作。2.现在要做pop操作,即要得到c,这时可以将q1中的a,b两个元素全部dequeue并存入q2中,这时q2中元素为a,b,对q1再做一次dequeue操作即可得到c。3.如果继续做push操作,比如插入d,f,则把d,f插入到q2中,4.此时若要做pop操作,则做步骤25.以此类推,就实现了用两个队列来实现一个栈的目的。注意在此过程中,新push进来的元素总是插入到非空队列中,空队列则用来保存pop操作之后的那些元素,那么 阅读全文

posted @ 2011-04-16 15:26 NULL00 阅读(1712) 评论(0) 推荐(0)

算法导论10.1-6习题解答(用两个栈实现一个队列)
摘要:CLRS10.1-6 :说明如何用两个栈来实现一个队列,并分析有关队列操作的运行时间。解法:1.有两个栈s1和s2,先往s1内插入a,b,c,这做的都是enqueue操作。2.现在要做dequeue操作,即要得到a,这时可以将s1中的元素全部弹出并存入s2中,这时s2中元素的顺序(从底部到顶部)为c,b,a,这时做s2.pop()操作即可得到a。3.如果继续做enqueue操作,比如插入d,f,则把d,f插入到s1中,4.此时若要做dequeue操作,则直接弹出s2中的b,它是目前为止,呆得时间最长的元素5.若继续做dequeue操作,则s2弹出c,6.若继续做dequeue操作,则s2为空, 阅读全文

posted @ 2011-04-16 15:12 NULL00 阅读(1637) 评论(0) 推荐(0)

算法导论10.1-5习题解答(deque实现源码)
摘要:CLRS 10.1-5栈的插入和删除操作都是在一端进行的,而队列的插入和删除却是在两头进行的。有一种双端队列(deque),其两端都可以做插入和删除的操作。对于一个用数组构造的双端队列,请写出四个在两端进行插入和删除操作的过程,要求运行时间为O(1)。#include <iostream>usingnamespace std;template <class T>class Deque{public: void push_front(T t); void push_back(T t); T pop_front(); T pop_back(); Deque(int m); 阅读全文

posted @ 2011-04-16 15:01 NULL00 阅读(1217) 评论(1) 推荐(0)

算法导论10.1-2习题解答(用一个数组实现两个栈)
摘要:CLRS 10.1-2 :说明如何用一个数组A[1...n]来实现两个栈,使得两个栈中的元素总数不到n时,两者都不会发生上溢。注意PUSH和POP操作的时间应为O(1)。解法:用top1指向数组第一个元素,用top2指向数组最后一个元素,然后PUSH的时候,它们向中间进发,POP的时候向相应的方向减一。 阅读全文

posted @ 2011-04-16 12:33 NULL00 阅读(1822) 评论(0) 推荐(0)

算法导论9.3-9习题解答(寻找中位数)
摘要:CLRS 9.3-9 :选择主输油管道的最优位置(使得各喷管长度总和最小的位置)。算法思想:1.当n为奇数时,其实就是求median;2.当n为偶数时,就是第n/2小和第n/2 + 1小的数为边界的闭区间的任何数。其实这个证明还是蛮简单的,可以移动x轴来观察情况,位于median处(n为奇数)或median范围内(n为偶数)时,设其距离为min,当移动x轴时,移出这个范围,则可以发现所有点(包括median点)到x轴的距离必然大于min。画一下图,就会一目了然。在这里用到了寻找第i小的数#include <iostream>#include <time.h>usingn 阅读全文

posted @ 2011-04-15 18:57 NULL00 阅读(4367) 评论(0) 推荐(0)

算法导论9.3-8习题解答(类似二分查找算法)
摘要:CLRS 9.3-8:设X[1...n]和Y[1...n]为两个数组,每个都包含n个已排序好的数。给出一个求数组X和Y中所有2n个元素的中位数的、O(lgn)时间的算法。算法思想:该算法类似于二分查找算法1.两个数组中小于median的个数为(n - 1)个,假设该median为数组a中的第k个,k为数组下标,那么在数组a中已经存在k个值小于median,那么在数组b中必然有(n - 1) - k = (n-k-1)个数小于median,如果b[n - k - 2] <= median <= b[n - k - 1],那么median就找到了,如果median >= b[n 阅读全文

posted @ 2011-04-15 17:12 NULL00 阅读(2891) 评论(2) 推荐(0)

算法导论9.3-7习题解答
摘要:CLRS 9.3-7 :给出一个O(n)时间的算法,在给定一个有n个不同数字的集合S以及一个正整数k<=n后,它能确定出S中最接近其中位数的k个数。算法思想:1.找到数组a中第n/2小的数median;2.对a中非median数进行|a[i] - median|,得到一个大小为n - 1的数组distance;3.寻找distance中第k小的数值;4.对distance进行一次遍历,找到小于等于k的数,从而对应得到数组a中的k个数。上述每一步的时间复杂度都为O(n),因而最后总的时间复杂度为O(n).#include <iostream>#include <time. 阅读全文

posted @ 2011-04-13 09:20 NULL00 阅读(1234) 评论(0) 推荐(0)

算法导论9.2-3习题解答(寻找第i小的数)
摘要:CLRS 9.2-3 :写出RANDOMIZED-SELECT的一个迭代版本在这里,顺便实现在数组内寻找第i小的数值。#include <iostream>#include <time.h>using namespace std;//随机化分割int randomized_partition(int* a, int p, int r);int randomized_select(int* a, int p, int r, int i);int main(){ int arr[10] = {4, 34, 21, 8, 3, 10, 453, 32, 1, 400}; in 阅读全文

posted @ 2011-04-12 19:56 NULL00 阅读(1500) 评论(0) 推荐(0)

算法导论9.1-1习题解答(二叉树)
摘要:CLRS 9.1-1 :证明:在最坏情况下,利用n + [lgn] - 2此比较,即可找到n个元素中的第2小元素。(提示:同时找最小元素)算法思想:1.将数组中的元素分组,每组两个元素,然后比较每组中的两个元素得到最小值,重新得到包含原来一半元素的数组,继续重复上述过程,那么最后一个元素必然为最小值。如图所示,数组为{2, 1, 4, 3, 5}2.上述过程形成的是一个二叉树,其中叶子节点都为数组元素,非叶子节点刚好4个,这是二叉树的性质。3.然后我们来找第二小元素,第二小元素必然跟着1,首先赋值为5,然后再赋值为3, 然后赋值为2,即为所求。PS:本章讨论的元素都互异,不存在相同值(见原书) 阅读全文

posted @ 2011-04-12 17:25 NULL00 阅读(2396) 评论(2) 推荐(0)

算法导论8-5习题解答(平均排序)
摘要:CLRS 8-5:平均排序解答:a)非递增完全排序b)2 1 4 3 6 5 8 7 10 9c)展开题目中的公式,然后消除相同项,即可得到此结论。d)算法思想: 1.将数组分成k组,即{a[0], a[k], a[2k] ...}, {a[1], a[1+k], a[zk+1] ...}, ..., {a[i], a[i+k], a[i+2k], ...}, ..., {a[k-1], a[2k-1], ...}. 2.然后对每一组用合并排序或者堆排序进行排序,则每一组的时间为t = n/k*lg(n/k),总的时间为nt,即nlg(n/k).e)由于数组已是k排序的,则可以将数组按d).1 阅读全文

posted @ 2011-04-11 21:06 NULL00 阅读(663) 评论(0) 推荐(0)

导航