算法导论第二十三章答案
算法导论课程作业答案
算法导论课程作业答案Introduction to AlgorithmsMassachusetts Institute of Technology 6.046J/18.410J Singapore-MIT Alliance SMA5503 Professors Erik Demaine,Lee Wee Sun,and Charles E.Leiserson Handout10Diagnostic Test SolutionsProblem1Consider the following pseudocode:R OUTINE(n)1if n=12then return13else return n+R OUTINE(n?1)(a)Give a one-sentence description of what R OUTINE(n)does.(Remember,don’t guess.) Solution:The routine gives the sum from1to n.(b)Give a precondition for the routine to work correctly.Solution:The value n must be greater than0;otherwise,the routine loops forever.(c)Give a one-sentence description of a faster implementation of the same routine. Solution:Return the value n(n+1)/2.Problem2Give a short(1–2-sentence)description of each of the following data structures:(a)FIFO queueSolution:A dynamic set where the element removed is always the one that has been in the set for the longest time.(b)Priority queueSolution:A dynamic set where each element has anassociated priority value.The element removed is the element with the highest(or lowest)priority.(c)Hash tableSolution:A dynamic set where the location of an element is computed using a function of the ele ment’s key.Problem3UsingΘ-notation,describe the worst-case running time of the best algorithm that you know for each of the following:(a)Finding an element in a sorted array.Solution:Θ(log n)(b)Finding an element in a sorted linked-list.Solution:Θ(n)(c)Inserting an element in a sorted array,once the position is found.Solution:Θ(n)(d)Inserting an element in a sorted linked-list,once the position is found.Solution:Θ(1)Problem4Describe an algorithm that locates the?rst occurrence of the largest element in a?nite list of integers,where the integers are not necessarily distinct.What is the worst-case running time of your algorithm?Solution:Idea is as follows:go through list,keeping track of the largest element found so far and its index.Update whenever necessary.Running time isΘ(n).Problem5How does the height h of a balanced binary search tree relate to the number of nodes n in the tree? Solution:h=O(lg n) Problem 6Does an undirected graph with 5vertices,each of degree 3,exist?If so,draw such a graph.If not,explain why no such graph exists.Solution:No such graph exists by the Handshaking Lemma.Every edge adds 2to the sum of the degrees.Consequently,the sum of the degrees must be even.Problem 7It is known that if a solution to Problem A exists,then a solution to Problem B exists also.(a)Professor Goldbach has just produced a 1,000-page proof that Problem A is unsolvable.If his proof turns out to be valid,can we conclude that Problem B is also unsolvable?Answer yes or no (or don’t know).Solution:No(b)Professor Wiles has just produced a 10,000-page proof that Problem B is unsolvable.If the proof turns out to be valid,can we conclude that problem A is unsolvable as well?Answer yes or no (or don’t know).Solution:YesProblem 8Consider the following statement:If 5points are placed anywhere on or inside a unit square,then there must exist two that are no more than √2/2units apart.Here are two attempts to prove this statement.Proof (a):Place 4of the points on the vertices of the square;that way they are maximally sepa-rated from one another.The 5th point must then lie within √2/2units of one of the other points,since the furthest from the corners it can be is the center,which is exactly √2/2units fromeach of the four corners.Proof (b):Partition the square into 4squares,each with a side of 1/2unit.If any two points areon or inside one of these smaller squares,the distance between these two points will be at most √2/2units.Since there are 5points and only 4squares,at least two points must fall on or inside one of the smaller squares,giving a set of points that are no more than √2/2apart.Which of the proofs are correct:(a),(b),both,or neither (or don’t know)?Solution:(b)onlyProblem9Give an inductive proof of the following statement:For every natural number n>3,we have n!>2n.Solution:Base case:True for n=4.Inductive step:Assume n!>2n.Then,multiplying both sides by(n+1),we get(n+1)n!> (n+1)2n>2?2n=2n+1.Problem10We want to line up6out of10children.Which of the following expresses the number of possible line-ups?(Circle the right answer.)(a)10!/6!(b)10!/4!(c) 106(d) 104 ·6!(e)None of the above(f)Don’t knowSolution:(b),(d)are both correctProblem11A deck of52cards is shuf?ed thoroughly.What is the probability that the4aces are all next to each other?(Circle theright answer.)(a)4!49!/52!(b)1/52!(c)4!/52!(d)4!48!/52!(e)None of the above(f)Don’t knowSolution:(a)Problem12The weather forecaster says that the probability of rain on Saturday is25%and that the probability of rain on Sunday is25%.Consider the following statement:The probability of rain during the weekend is50%.Which of the following best describes the validity of this statement?(a)If the two events(rain on Sat/rain on Sun)are independent,then we can add up the twoprobabilities,and the statement is true.Without independence,we can’t tell.(b)True,whether the two events are independent or not.(c)If the events are independent,the statement is false,because the the probability of no rainduring the weekend is9/16.If they are not independent,we can’t tell.(d)False,no matter what.(e)None of the above.(f)Don’t know.Solution:(c)Problem13A player throws darts at a target.On each trial,independentlyof the other trials,he hits the bull’s-eye with probability1/4.How many times should he throw so that his probability is75%of hitting the bull’s-eye at least once?(a)3(b)4(c)5(d)75%can’t be achieved.(e)Don’t know.Solution:(c),assuming that we want the probability to be≥0.75,not necessarily exactly0.75.Problem14Let X be an indicator random variable.Which of the following statements are true?(Circle all that apply.)(a)Pr{X=0}=Pr{X=1}=1/2(b)Pr{X=1}=E[X](c)E[X]=E[X2](d)E[X]=(E[X])2Solution:(b)and(c)only。
算法设计与分析习题解答
算法设计与分析习题解答第一章作业1.证明下列Ο、Ω和Θ的性质1)f=Ο(g)当且仅当g=Ω(f)证明:充分性。
若f=Ο(g),则必然存在常数c1>0和n0,使得?n≥n0,有f≤c1*g(n)。
由于c1≠0,故g(n) ≥ 1/ c1 *f(n),故g=Ω(f)。
必要性。
同理,若g=Ω(f),则必然存在c2>0和n0,使得?n≥n0,有g(n) ≥ c2 *f(n).由于c2≠0,故f(n) ≤ 1/ c2*f(n),故f=Ο(g)。
2)若f=Θ(g)则g=Θ(f)证明:若f=Θ(g),则必然存在常数c1>0,c2>0和n0,使得?n≥n0,有c1*g(n) ≤f(n) ≤ c2*g(n)。
由于c1≠0,c2≠0,f(n) ≥c1*g(n)可得g(n) ≤ 1/c1*f(n),同时,f(n) ≤c2*g(n),有g(n) ≥ 1/c2*f(n),即1/c2*f(n) ≤g(n) ≤ 1/c1*f(n),故g=Θ(f)。
3)Ο(f+g)= Ο(max(f,g)),对于Ω和Θ同样成立。
证明:设F(n)= Ο(f+g),则存在c1>0,和n1,使得?n≥n1,有F(n) ≤ c1 (f(n)+g(n))= c1 f(n) + c1g(n)≤ c1*max{f,g}+ c1*max{f,g}=2 c1*max{f,g}所以,F(n)=Ο(max(f,g)),即Ο(f+g)= Ο(max(f,g))对于Ω和Θ同理证明可以成立。
4)log(n!)= Θ(nlogn)证明:由于log(n!)=∑=ni i 1log ≤∑=ni n 1log =nlogn ,所以可得log(n!)= Ο(nlogn)。
由于对所有的偶数n 有,log(n!)= ∑=ni i 1log ≥∑=nn i i 2/log ≥∑=nn i n 2/2/log ≥(n/2)log(n/2)=(nlogn)/2-n/2。
藏书阁-《算法导论》常见算法总结
常见算法总结分治法分治策略的思想:顾名思义,分治是将一个原始问题分解成多个子问题,而子问题的形式和原问题一样,只是规模更小而已,通过子问题的求解,原问题也就自然出来了。
总结一下,大致可以分为这样的三步:分解:将原问题划分成形式相同的子问题,规模可以不等,对半或2/3对1/3的划分。
解决:对于子问题的解决,很明显,采用的是递归求解的方式,如果子问题足够小了,就停止递归,直接求解。
合并:将子问题的解合并成原问题的解。
这里引出了一个如何求解子问题的问题,显然是采用递归调用栈的方式。
因此,递归式与分治法是紧密相连的,使用递归式可以很自然地刻画分治法的运行时间。
所以,如果你要问我分治与递归的关系,我会这样回答:分治依托于递归,分治是一种思想,而递归是一种手段,递归式可以刻画分治算法的时间复杂度。
所以就引入本章的重点:如何解递归式?分治法适用的情况分治法所能解决的问题一般具有以下几个特征:1. 该问题的规模缩小到一定的程度就可以容易地解决2. 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
3. 利用该问题分解出的子问题的解可以合并为该问题的解;4. 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用;、第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。
第四条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。
——————————————————————————————最大堆最小堆1、堆堆给人的感觉是一个二叉树,但是其本质是一种数组对象,因为对堆进行操作的时候将堆视为一颗完全二叉树,树种每个节点与数组中的存放该节点值的那个元素对应。
算法导论参考问题详解
第二章算法入门由于时间问题有些问题没有写的很仔细,而且估计这里会存在不少不恰当之处。
另,思考题2-3 关于霍纳规则,有些部分没有完成,故没把解答写上去,我对其 c 问题有疑问,请有解答方法者提供个意见。
给出的代码目前也仅仅为解决问题,没有做优化,请见谅,等有时间了我再好好修改。
插入排序算法伪代码INSERTION-SORT(A)1 for j ←2 to length[A]2 do key ←A[j]3 Insert A[j] into the sorted sequence A[1..j-1]4 i ←j-15 while i > 0 and A[i] >6 do A[i+1]←A[i]7 i ←i − 18 A[i+1]←keyC#对揑入排序算法的实现:public static void InsertionSort<T>(T[] Input) where T:IComparable<T>{T key;int i;for (int j = 1; j < Input.Length; j++){key = Input[j];i = j - 1;for (; i >= 0 && Input[i].CompareTo(key)>0;i-- )Input[i + 1] = Input[i];Input[i+1]=key;}}揑入算法的设计使用的是增量(incremental)方法:在排好子数组A[1..j-1]后,将元素A[ j]揑入,形成排好序的子数组A[1..j]这里需要注意的是由于大部分编程语言的数组都是从0开始算起,这个不伪代码认为的数组的数是第1个有所丌同,一般要注意有几个关键值要比伪代码的小1.如果按照大部分计算机编程语言的思路,修改为:INSERTION-SORT(A)1 for j ← 1 to length[A]2 do key ←A[j]3 i ←j-14 while i ≥ 0 and A[i] >5 do A[i+1]←A[i]6 i ←i − 17 A[i+1]←key循环丌变式(Loop Invariant)是证明算法正确性的一个重要工具。
中科大算法导论第一,二次和第四次作业答案
2.2-3 再次考虑线性查找问题 (见练习2.1-3)。在平均情况 下,需要检查输入序列中的多 少个元素?假定待查找的元素 是数组中任何一个元素的可能 性是相等的。在最坏情况下有 怎样呢?用Θ形式表示的话,线 性查找的平均情况和最坏情况 运行时间怎样?对你的答案加 以说明。 • 线性查找问题 • 输入:一列数A=<a1,a2,…,an>和一 个值v。 • 输出:下标i,使得v=A[i],或者当 v不在A中出现时为NIL。 • 平均情况下需要查找 (1+2+…+n)/n=(n+1)/2 • 最坏情况下即最后一个元素为待 查找元素,需要查找n个。 • 故平均情况和最坏情况的运行时 间都为Θ(n)。
• 2.3-2改写MERGE过程,使之不使 用哨兵元素,而是在一旦数组L或R 中的所有元素都被复制回数组A后, 就立即停止,再将另一个数组中 余下的元素复制回数组A中。 • MERGE(A,p,q,r) 1. n1←q-p+1 2. n2 ←r-q 3. create arrays L[1..n1] and R[1..n2] 4. for i ←1 to n1 5. do L*i+ ←A*p+i-1] 6. for j ←1 to n2 7. do R*j+ ←A*q+j+ 8. i ←1 9. j ←1
10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
k ←p while((i<=n1) and (j<=n2)) do if L[i]<=R[j] do A[k]=L[i] i++ else do A[k]=R[j] j++ k++ while(i<=n1) do A[k++]=L[i++] while(j<=n2) do A[k++]=R[j++]
《算法导论(第二版)》(中文版)课后答案
17.3-1
11
《算法导论(第二版) 》参考答案
17.3-4
17.4-3 假设第 i 个操作是 TABLE_DELETE, 考虑装载因子 : i =(第 i 次循环之后的表 中的 entry 数)/(第 i 次循环后的表的大小)= numi / sizei
19.1-1. If x is not a root node, then Degree[x]=Degree[sibling[x]]+1 If x is a root node, then Degree[x]<Degree[sibling[x]] 19.1-2
13.1-5 prove:
3
《算法导论(第二版) 》参考答案 13.1-6 2k-1 22k-1 13.2-3 13.3-5
13.4-3
4
《算法导论(第二版) 》参考答案
14.1-4
14.2-2
14.2-3 不可以,性能改变 时间复杂度由 O( lgn ) -> O( nlgn )
14.3-2 Note: 注意 Overlap 的定义稍有不同,需要重新定义。 算法:只要将 P314 页第三行的 改成>就行。 14.3-3 INTERVAL-SEARCH-SUBTREE(x, i) 1 while x ≠ nil[T] and i does not overlap int[x] 2 do if left[x] ≠ nil[T] and max[left[x]] ≥ low[i] 3 then x ← left[x] 4 else x ← right[x] 5 return x INTERVAL-SEARCH-MIN(T, i) 2 y←INTERVAL-SEARCH-SUBTREE(root[T], i) 先找第一个重叠区间 3 z←y 4 while y≠ nil[T] and left[y] ≠ nil[T] 在它的左子树上查找
(完整版)算法导论复习要点
一、基础知识部分1. 算法的复杂性有时间复杂性和空间复杂性之分。
2. 算法是由若干条指令组成的有穷序列,且要满足输入、输出、确定性和有限性四条性质。
3. 快速排序算法是基于分治策略的一种排序算法。
4. 矩阵连乘问题的算法可由动态规划设计实现。
5、算法是指解决问题的一种方法或一个过程。
6、从分治法的一般设计模式可以看出,用它设计出的程序一般是递归算法。
7、问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。
8、贪心选择性质是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
9. 贪心算法的基本要素是贪心选择质和最优子结构性质。
10. 动态规划算法的两个基本要素是最优子结构性质和重叠子问题性质。
11、合并排序算法是利用(A )实现的算法A、分治策略B、动态规划法C、贪心法D、回溯法12、下列不是动态规划算法基本步骤的是( A )。
A、找出最优解的性质B、构造最优解C、算出最优解D、定义最优解13.下列算法中通常以自底向上的方式求解最优解的是( B )。
A、备忘录法B动态规划法C、贪心法D回溯法14. 备忘录方法是那种算法的变形。
(B )A、分治法B动态规划法C、贪心法D回溯法15.最长公共子序列算法利用的算法是( B )。
A、分支界限法B动态规划法C贪心法D回溯法16.贪心算法与动态规划算法的主要区别是( B )。
A、最优子结构B、贪心选择性质C、构造最优解D、定义最优解17. (D )是贪心算法与动态规划算法的共同点。
A、重叠子问题B、构造最优解C、贪心选择性质D最优子结构性质18. 矩阵连乘问题的算法可由(B )设计实现。
A、分支界限算法 B 、动态规划算法C、贪心算法D、回溯算法19、使用分治法求解不需要满足的条件是( A )。
A 子问题必须是一样的B 子问题不能够重复C 子问题的解可以合并D 原问题和子问题使用相同的方法解20.下列是动态规划算法基本要素的是( D )。
算法导论32章答案
算法导论32章答案32 String Matching32.1-2Suppose that all characters in the pattern P are different. Show how to accelerate NAIVE-STRING-MATCHER to run in timeO.n/ on an n-character text T.Naive-Search(T,P)for s = 1 to n – m + 1j = 0while T[s+j] == P[j] doj = j + 1if j = m return ss = j + s;该算法实际只是会扫描整个字符串的每个字符⼀次,所以其时间复杂度为O(n).31.1-3Suppose that pattern P and text T are randomly chosen strings of length m and n, respectively, from the d-ary alphabet ∑d ={0,1,2,..,d-1},where d ≧ 2.Show that the expected number of character-to-character comparisons made by the implicit loop inline 4 of the naive algorithm isover all executions of this loop. (Assume that the naive algorithm stops comparing characters for a given shift once it finds amismatch or matches the entire pattern.) Thus, for randomly chosen strings, the naive algorithm is quite efficient.当第4⾏隐含的循环执⾏i次时,其概率P为:P = 1/K i-1 * (1-1/k), if i < mP = 1/K m-1 * (1-1/k) + 1/K m , if i = m可以计算每次for循环迭代时,第4⾏的循环的平均迭代次数为:[1*(1-1/k)+2*(1/K)*(1-1/k)+3*(1/k2)(1-1/k)+…+(m-1)*(1-k m-2)(1-1/k) +m*(1/k m-1)(1-1/k) + m*(1/k m)]= 1 - 1/k + 2/k - 2/k2 + 3/k2 - 3/k3 +...+ m/k m-1 - m/k m + m/k m= 1 + 1/k + 1/k2 +...+ 1/k m-1= (1 - 1/K m) / (1 - 1/k)≤ 2所以,可知,第4⾏循环的总迭代次数为:(n-m+1) * [(1-1/K m) / (1-1/k)] ≤ 2 (n-m+1)31.1-4Suppose we allow the pattern P to contain occurrences of a gap character } that can match an arbitrary string of characters(even one of zero length). For example, the pattern ab}ba}c occurs in the text cabccbacbacab asand asNote that the gap character may occur an arbitrary number of times in the pattern but not at all in the text. Give a polynomial-time algorithm to determine whether such a pattern P occurs in a given text T, and analyze the running time of your algorithm.该算法只是要求判断是否模式P出现在该字符串中,那么问题被简化了许多。
中科大算法导论作业标准标准答案
第8次作业答案16.1-116.1-2543316.3-416.2-5参考答案:16.4-1证明中要三点:1.有穷非空集合2.遗传性3.交换性第10次作业参考答案16.5-1题目表格:解法1:使用引理16.12性质(2),按wi单调递减顺序逐次将任务添加至Nt(A),每次添加一个元素后,进行计算,{计算方法:Nt(A)中有i个任务时计算N0 (A),…,Ni(A),其中如果存在Nj (A)>j,则表示最近添加地元素是需要放弃地,从集合中删除};最后将未放弃地元素按di递增排序,放弃地任务放在所有未放弃任务后面,放弃任务集合内部排序可随意.解法2:设所有n个时间空位都是空地.然后按罚款地单调递减顺序对各个子任务逐个作贪心选择.在考虑任务j时,如果有一个恰处于或前于dj地时间空位仍空着,则将任务j赋与最近地这样地空位,并填入; 如果不存在这样地空位,表示放弃.答案(a1,a2是放弃地):<a5, a4, a6, a3, a7,a1, a2>or <a5, a4, a6, a3, a7,a2, a1>划线部分按上表di递增地顺序排即可,答案不唯一16.5-2(直接给个计算例子说地不清不楚地请扣分)题目:本题地意思是在O(|A|)时间内确定性质2(性质2:对t=0,1,2,…,n,有Nt(A)<=t,Nt(A)表示A中期限不超过t地任务个数)是否成立.解答示例:思想:建立数组a[n],a[i]表示截至时间为i地任务个数,对0=<i<n,如果出现a[0]+a[1]+…+a[i]>i,则说明A不独立,否则A独立.伪代码:int temp=0;for(i=0;i<n;i++) a[i]=0; ******O(n)=O(|A|)for(i=0;i<n;i++) a[di]++; ******O(n)=O(|A|)for(i=0;i<n;i++) ******O(n)=O(|A|) {temp+=a[i];//temp就是a[0]+a[1]+…+a[i]if(temp>i)//Ni(A)>iA不独立;}17.1-1(这题有歧义,不扣分)a) 如果Stack Operations包括Push Pop MultiPush,答案是可以保持,解释和书上地Push Pop MultiPop差不多.b) 如果是Stack Operations包括Push Pop MultiPush MultiPop,答案就是不可以保持,因为MultiPush,MultiPop交替地话,平均就是O(K).17.1-2本题目只要证明可能性,只要说明一种情况下结论成立即可17.2-1第11次作业参考答案17.3-1题目:答案:备注:最后一句话展开:采用新地势函数后对i 个操作地平摊代价:)1()())1(())(()()(1''^'-Φ-Φ+=--Φ--Φ+=Φ-Φ+=-Di Di c k Di k Di c D D c c i i i i i i17.3-2题目:答案:第一步:此题关键是定义势能函数Φ,不管定义成什么首先要满足两个条件 对所有操作i ,)(Di Φ>=0且)(Di Φ>=)(0D Φ比如令k j+=2i ,j,k 均为整数且取尽可能大,设势能函数)(Di Φ=2k;第二步:求平摊代价,公式是)1()(^-Φ-Φ+=Di Di c c i i 按上面设置地势函数示例:当k=0,^i c =…=2当k !=0,^i c =…=3 显然,平摊代价为O(1)17.3-4题目:答案:结合课本p249,p250页对栈操作地分析很容易有下面结果17.4-3题目:答案:αα=(第i次循环之后地表中地entry 假设第i个操作是TABLE_DELETE, 考虑装载因子:inum size数)/(第i次循环后地表地大小)=/i i第12 次参考答案19.1.1题目:答案:如果x不是根,则degree[sibling[x]]=degree[child[x]]=degree[x]-1如果x是根,则sibling为二项堆中下一个二项树地根,因为二项堆中根链是按根地度数递增排序,因此degree[sibling[x]]>degree[x]19.1.2题目:答案:如果x是p[x]地最左子节点,则p[x]为根地子树由两个相同地二项树合并而成,以x为根地子树就是其中一个二项树,另一个以p[x]为根,所以degree[p[x]]=degree[x]+1;如果x不是p[x]地最左子节点,假设x是p[x]地子节点中自左至右地第i个孩子,则去掉p[x]前i-1个孩子,恰好转换成第一种情况,因而degree[p[x]]=degree[x]+1+(i-1)=degree[x]+i;综上,degree[p[x]]>degree[x]19.2.2题目:题目:19.2.519.2.6第13次作业参考答案20.2-1题目:解答:20.2-3 题目:解答:20.3-1 题目:答案:20.3-2 题目:答案:第14次作业参考答案这一次请大家自己看书处理版权申明本文部分内容,包括文字、图片、以及设计等在网上搜集整理.版权为个人所有This article includes some parts, including text, pictures, and design. Copyright is personal ownership.6ewMy。
算法(第四版)C#习题题解——2.3
算法(第四版)C#习题题解——2.3写在前⾯习题&题解2.3.1解答2.3.2解答2.3.3解答N / 2在快速排序中,⼀个元素要被交换,有以下两种情况1.该元素是枢轴,在切分的最后⼀步被交换2.该元素位于枢轴错误的⼀侧,需要被交换到另⼀侧去注意,以上两种情况在⼀次切分中只会出现⼀次⾸先来看第⼀种情况,如果⼀个元素变成了枢轴那么在之后的切分中该元素会被排除,不存在后续的交换。
因此我们的⽬标应该是:最⼤的元素总是出现在错误的⼀侧,同时切分的次数尽可能多。
接下来我们来思考如何构造这样的数组由于我们针对的是最⼤的元素,因此「错误的⼀侧」就是枢轴的左侧。
为了使切分的次数尽可能多,我们需要保持最⼤值移动的距离尽量短。
但如果每次只移动⼀位的话,下⼀次切分时最⼤值就会变成枢轴例如 4 10 3 5 6,枢轴为 4,交换后数组变为:4 3 105 6随后 4 和 3 交换3 4 10 5 6下⼀次切分时 10 会变成枢轴,不再参与后续的切分。
因此我们需要让最⼤值每次移动两个元素。
考虑下⾯的数组:2 10 4 1 63 8 5 7 9第⼀次切分的时候,枢轴为 2,10 和 1 进⾏交换数组变为:2 1 4 10 63 8 5 7 9随后枢轴交换,数组变为:1 2 4 10 6 3 8 5 7 9第⼆次切分,枢轴为 4,10 和 3 进⾏交换。
1 2 4 3 6 10 8 5 7 9随后枢轴交换数组变为:1 2 3 4 6 10 8 5 7 9第三次切分,枢轴为 6,10 和 5 交换1 2 3 4 6 5 8 10 7 9随后枢轴交换,数组变为:1 2 3 4 5 6 8 10 7 9第四次切分,枢轴为 8,10 和 7 交换1 2 3 4 5 6 8 7 10 9枢轴交换,数组变为1 2 3 4 5 6 7 8 10 9最后⼀次切分,枢轴为 10,直接交换1 2 3 4 5 6 7 8 9 10我们可以总结出要构造这样的数组的模板a2 max a3 a1其中 a1 < a2 < a3 < maxmax 每轮切分移动两格,总共切分 N/ 2 次。
算法导论习题
//在合并排序中对小数组采用插入排序#include<stdio.h>void main(){void MERGE_SORT(int a[],int p,int r,int k);int a[12]; //={3,0,1,10,9,5,4,12,7,8,2,6};int k=3,n=12;int i,j,s;int tmp=0;printf("请输入12个正整数:\n");for(i=0;i<12;i++)scanf("%d",&a[i]);for(i=0;i<=3;i++){for(j=i*3+1;j<i*3+3;j++){s=j;while(s>=i*3+1){if(a[s]<a[s-1])tmp=a[s],a[s]=a[s-1],a[s-1]=tmp;s--;}}}printf("第一步对4个长度3的子列表进行插入排序的结果为:\n");for(i=0;i<12;i++)printf("%d,",a[i]);printf("\n");MERGE_SORT(a,0,3,3);printf("第二步对4个子列表进行合并排序的结果为:\n");for(i=0;i<12;i++)printf("%d,",a[i]);printf("\n");} void MERGE_SORT(int a[],int p,int r,int k) {void MERGE(int a[],int p,int q,int r,int k);int q;if(p<r){q=(p+r)/2;MERGE_SORT(a,p,q,k);MERGE_SORT(a,q+1,r,k);MERGE(a,p,q,r,k);}}void MERGE(int a[],int p,int q,int r,int k) {int n1=(q-p+1)*k,n2=(r-q)*k;int i,j,s;int *L=new int[n1];int *R=new int[n2];for(i=0;i<n1;i++)L[i]=a[p*k+i];for(j=0;j<n2;j++)R[j]=a[(q+1)*k+j];i=0;j=0;for(s=p*3;s<=(r+1)*3-1;s++){if(i>n1-1)a[s]=R[j++];else if(j>n2-1)a[s]=L[i++];else if(L[i]<R[j])a[s]=L[i++];elsea[s]=R[j++];}}//用分治法在数组中查找逆序对#include<stdio.h>void main(){int count_inversion(int a[],int p,int r);int a[5]={5,4,3,2,1};printf("数组的逆序对是%d个\n",count_inversion(a,0,4));}int merge_inversion(int a[],int p,int q,int r){int n1=q-p+1;int n2=r-q;int *L=new int[n1];int *R=new int[n2];int i,j,k,v;for(i=0;i<n1;++i)L[i]=a[p+i];for(j=0;j<n2;++j)R[j]=a[q+1+j];i=0;j=0;v=0;for(k=p;k<=r;++k){if(i>n1-1)a[k]=R[j++];else if(j>n2-1)a[k]=L[i++];else if(L[i]>R[j]){a[k]=R[j++];v+=n1-i;}elsea[k]=L[i++];}delete L;delete R;return v;}int count_inversion(int a[],int p,int r){int v=0,q;if(p<r){q=(p+r)/2;v+=count_inversion(a,p,q);v+=count_inversion(a,q+1,r);v+=merge_inversion(a,p,q,r);}return v;}//用插入方法建堆#include"stdio.h"void HEAP_INCREASE_KEY(int a[],int i,int key) {int tmp;if(key>a[i-1])a[i-1]=key;while(i>1&&a[i/2-1]<a[i-1]){tmp=a[i/2-1],a[i/2-1]=a[i-1],a[i-1]=tmp;i=i/2;}}void MAX_HEAP_INSERT(int a[],int key,int heap_size){heap_size+=1;a[heap_size-1]=0;HEAP_INCREASE_KEY(a,heap_size,key); }void BUILD_MAX_HEAP(int a[],int lengh){int heap_size=1;int i;for(i=2;i<=lengh;i++){MAX_HEAP_INSERT(a,a[i-1],heap_size);heap_size++; //堆的长度要随着循环的次数增长}}void main(){int j;int a[10]={15,84,62,16,29,35,6,18,9,17};BUILD_MAX_HEAP(a,10);for(j=0;j<10;j++)printf("%d\n",a[j]);}#include"stdio.h"void MAX_D_HEAPIFY(int a[],int i,int d,int heap_size){int n=d,j,largest;int tmp;int *child=new int[n];for(j=0;j<n;j++)child[j]=(i-1)*d+2+j;if(child[0]<=heap_size&&a[child[0]-1]>a[i-1])largest=child[0];elselargest=i;for(j=1;j<n;j++){if(child[j]<=heap_size&&a[child[j]-1]>a[largest-1])largest=child[j];}if(largest!=i){tmp=a[largest-1],a[largest-1]=a[i-1],a[i-1]=tmp;MAX_D_HEAPIFY(a,largest,d,heap_size);}}void BUILD_MAX_D_HEAP(int a[],int d,int heap_size){int i,j;j=heap_size%d;if(j==0||j==1)i=heap_size/d;elsei=heap_size/d+1;//由叶子节点求父节点有两种情况for(i;i>=1;i--)MAX_D_HEAPIFY(a,i,d,heap_size);}int EXTRACT_MAX(int a[],int d,int heap_size) {int tmp;tmp=a[heap_size-1];a[heap_size-1]=a[0];a[0]= tmp;heap_size--;MAX_D_HEAPIFY(a,1,d,heap_size);return a[heap_size];}void main(){inta[20]={52,47,16,58,23,26,14,18,59,68,47,19,35,29, 61,82,74,75,98,81};// int b[18]={25,11,15,9,8,17,21,40,18,11,10,20,14,15,19, 21,7,10};int d=5,j,largest;BUILD_MAX_D_HEAP(a,5,20);// BUILD_MAX_D_HEAP(b,5,18);for(j=0;j<20;j++)printf("%d\n",a[j]);largest=EXTRACT_MAX(a,5,20);for(j=0;j<20;j++)printf("%d\n",a[j]);printf("%d\n",largest);/* for(j=0;j<18;j++)printf("%d\n",b[j]);*/#include"stdio.h"void MAX_D_HEAPIFY(int a[],int i,int d,int heap_size){int n=d,j,largest;int tmp;int *child=new int[n];for(j=0;j<n;j++)child[j]=(i-1)*d+2+j;if(child[0]<=heap_size&&a[child[0]-1]>a[i-1])largest=child[0];elselargest=i;for(j=1;j<n;j++){if(child[j]<=heap_size&&a[child[j]-1]>a[largest-1])largest=child[j];}if(largest!=i){tmp=a[largest-1],a[largest-1]=a[i-1],a[i-1]=tmp;MAX_D_HEAPIFY(a,largest,d,heap_size);}}void BUILD_MAX_D_HEAP(int a[],int d,int heap_size){int i,j;j=heap_size/d;if(j==0||j==1)i=heap_size/d;elsei=heap_size/d+1;//由叶子节点求父节点有两种情况for(i;i>=1;i--)MAX_D_HEAPIFY(a,i,d,heap_size);}void HEAP_INCREASE_KEY(int a[],int i,int d,int key){int tmp,j;if(a[i-1]<=key)a[i-1]=key;while(i>1){if(i%d==0||i%d==1)j=i/d;elsej=i/d+1;if(a[j-1]<a[i-1]){tmp=a[j-1],a[j-1]=a[i-1],a[i-1]=tmp;i=j;}else break;}}void INSERT(int a[],int key,int d,int heap_size) {heap_size+=1;a[heap_size-1]=0;HEAP_INCREASE_KEY(a,heap_size,d,key); }void main(){inta[20]={52,47,16,58,23,26,14,18,59,68,47,19,35,29, 61,82,74,75,98,81};int j,s=0;BUILD_MAX_D_HEAP(a,5,19);for(j=0;j<20;j++){printf("%d,",a[j]);s+=1;if(s%6==0)printf("\n");}INSERT(a,a[19],5,19);s=0;printf("\n");for(j=0;j<20;j++){printf("%d,",a[j]);s+=1;if(s%6==0)printf("\n");}}#include"stdio.h"void MAX_D_HEAPIFY(int a[],int i,int d,int heap_size){int n=d,j,largest;int tmp;int *child=new int[n];for(j=0;j<n;j++)child[j]=(i-1)*d+2+j;if(child[0]<=heap_size&&a[child[0]-1]>a[i-1])largest=child[0];elselargest=i;for(j=1;j<n;j++){if(child[j]<=heap_size&&a[child[j]-1]>a[largest-1])largest=child[j];}if(largest!=i){tmp=a[largest-1],a[largest-1]=a[i-1],a[i-1]=tmp;MAX_D_HEAPIFY(a,largest,d,heap_size);}}void BUILD_MAX_D_HEAP(int a[],int d,int heap_size){int i,j;j=heap_size/d;if(j==0||j==1)i=heap_size/d;elsei=heap_size/d+1;//由叶子节点求父节点有两种情况for(i;i>=1;i--)MAX_D_HEAPIFY(a,i,d,heap_size);}void HEAP_DECREASE_KEY(int a[],int i,int d,int key,int heap_size){if(a[i-1]>=key)a[i-1]=key;MAX_D_HEAPIFY(a,i,d,heap_size);}void main(){inta[20]={52,47,16,58,23,26,14,18,59,68,47,19,35,29, 61,82,74,75,98,81};int key=1,s=0,j;BUILD_MAX_D_HEAP(a,5,20);for(j=0;j<20;j++){printf("%d,",a[j]);s+=1;if(s%6==0)printf("\n");}printf("\n");s=0;HEAP_DECREASE_KEY(a,3,5,key,20);for(j=0;j<20;j++){printf("%d,",a[j]);s+=1;if(s%6==0)printf("\n");}}#include"stdio.h"void main(){//int a[10]={6,4,12,7,9,11,5,13,18,8};int a[10]={20,18,17,14,16,10,8,9,8,15};int i=9,j;int heap_size;void BULD_MAX_HEAP(int a[]);int HEAP_DELETE(int a[],int i);BULD_MAX_HEAP(a);heap_size=HEAP_DELETE(a,i);printf("删除第i个元素后的堆是:\n");for(j=0;j<heap_size;j++)printf("%d\n",a[j]);}void BULD_MAX_HEAP(int a[]){void MAX_HEAPIFY(int a[],int j,int heap_size);int heap_size=10;int j;for(j=4;j>=0;j--)MAX_HEAPIFY(a,j,heap_size);printf("堆a是:\n");for(j=0;j<heap_size;j++)printf("%4d",a[j]);printf("\n");}void MAX_HEAPIFY(int a[],int j,int heap_size) {int left=2*(j+1);int right=2*(j+1)+1;//结点与数组下标之间要转换int largest=0,temp;if(left<=heap_size&&a[left-1]>a[j])largest=left-1;elselargest=j;if(right<=heap_size&&a[right-1]>a[largest])largest=right-1;if(largest!=j){temp=a[largest];a[largest]=a[j];a[j]=temp;MAX_HEAPIFY(a,largest,heap_size);}}int HEAP_DELETE(int a[],int i){int temp,key=a[9],key1=a[i-1];int heap_size=10;temp=a[9];a[9]=a[i-1];a[i-1]=temp;heap_size--;if(key>key1){while(i>1&&a[i/2-1]<a[i-1])//如果a[9]大于i结点的值,则通过不断与父结点的比较//来确它的位置{temp=a[i/2-1],a[i/2-1]=a[i-1],a[i-1]=temp;i=i/2;}}elseMAX_HEAPIFY(a,i-1,heap_size);//如果a[9]比i结点的值要小,则从i结点开始堆维护return heap_size;}//建立最小堆#include"stdio.h"void MIN_HEAPIFY(int a[],int i,int heap_size){int small,tmp;int left=2*i,right=2*i+1;if(left<=heap_size&&a[left-1]>a[i-1])small=left;elsesmall=i;if(right<=heap_size&&a[right-1]>a[small-1]) small=right;if(small!=i){tmp=a[small-1],a[small-1]=a[i-1],a[i-1]=tmp;MIN_HEAPIFY(a,small,heap_size);}}void BUILD_MIN_HEAP(int a[],int heap_size) {int i;for(i=(heap_size/2);i>=1;i--)MIN_HEAPIFY(a,i,heap_size);}void HEAPSORT(int a[],int lengh){int i,tmp;int heap_size=lengh;BUILD_MIN_HEAP(a,heap_size);for(i=lengh;i>=2;i--){tmp=a[i-1],a[i-1]=a[0],a[0]=tmp;heap_size--;MIN_HEAPIFY(a,1,heap_size);}}void main(){int a[10]={23,6,21,3,7,5,8,54,14,10};int i;HEAPSORT(a,10);for(i=0;i<10;i++)printf("%d\n",a[i]);}//PARTITION的最初版本#include"stdio.h" int HOARE_PARTITION(int a[],int p,int r){int x,tmp;int i,j;x=a[p-1];i=p-1;j=r+1;while(1){while(a[--j-1]>x);while(a[++i-1]<x);if(i<j)tmp=a[i-1],a[i-1]=a[j-1],a[j-1]=tmp;elsereturn j;}}void QUICK_SORT(int a[],int p,int r){int q;if(p<r){q=HOARE_PARTITION(a,p,r);QUICK_SORT(a,p,q);QUICK_SORT(a,q+1,r);}}void main(){int i;inta[20]={10,58,46,23,26,48,47,59,68,23,12,19,17,24, 43,81,76,72,98,46};QUICK_SORT(a,1,20);for(i=0;i<20;i++)printf("%d\n",a[i]);/*对插入排序来说,当其输入已“几乎”排好序时,运行时间是很快的。
算法导论标准答案
算法导论标准答案————————————————————————————————作者:————————————————————————————————日期:2第二章算法入门由于时间问题有些问题没有写的很仔细,而且估计这里会存在不少不恰当之处。
另,思考题2-3 关于霍纳规则,有些部分没有完成,故没把解答写上去,我对其 c 问题有疑问,请有解答方法者提供个意见。
给出的代码目前也仅仅为解决问题,没有做优化,请见谅,等有时间了我再好好修改。
插入排序算法伪代码INSERTION-SORT(A)1 for j ←2 to length[A]2 do key ←A[j]3 Insert A[j] into the sorted sequence A[1..j-1]4 i ←j-15 while i > 0 and A[i] > key6 do A[i+1]←A[i]7 i ←i − 18 A[i+1]←keyC#对揑入排序算法的实现:public static void InsertionSort<T>(T[] Input) where T:IComparable<T>{T key;int i;for (int j = 1; j < Input.Length; j++){key = Input[j];i = j - 1;for (; i >= 0 && Input[i].CompareTo(key)>0;i-- )Input[i + 1] = Input[i];Input[i+1]=key;}}揑入算法的设计使用的是增量(incremental)方法:在排好子数组A[1..j-1]后,将元素A[ j]揑入,形成排好序的子数组A[1..j]这里需要注意的是由于大部分编程语言的数组都是从0开始算起,这个不伪代码认为的数组的数是第1个有所丌同,一般要注意有几个关键值要比伪代码的小1.如果按照大部分计算机编程语言的思路,修改为:INSERTION-SORT(A)1 for j ← 1 to length[A]2 do key ←A[j]3 i ←j-112 31 41 59 26 41 584 while i ≥ 0 and A[i] > key5 do A[i+1]←A[i]6 i ← i − 17A[i+1]←key循环丌变式(Loop Invariant)是证明算法正确性的一个重要工具。
算法导论第三版答案
Procedure BINARY-SEARCH takes a sorted array A, a value , and a range Œlow : : high of the array, in which we search for the value . The procedure compares to the array entry at the midpoint of the range and decides to eliminate half the range from further consideration. We give both iterative and recursive versions, each of which returns either an index i such that AŒi D , or NIL if no utions for Chapter 2: Getting Started
AŒlow : : high contains the value . The initial call to either version should have the parameters A; ; 1; n.
Selected Solutions for Chapter 2: Getting Started
2-3
d. We follow the hint and modify merge sort to count the number of inversions in ‚.n lg n/ time.
To start, let us define a merge-inversion as a situation within the execution of merge sort in which the MERGE procedure, after copying AŒp : : q to L and AŒq C 1 : : r to R, has values x in L and y in R such that x > y. Consider an inversion .i; j /, and let x D AŒi and y D AŒj , so that i < j and x > y. We claim that if we were to run merge sort, there would be exactly one mergeinversion involving x and y. To see why, observe that the only way in which array elements change their positions is within the MERGE procedure. Moreover, since MERGE keeps elements within L in the same relative order to each other, and correspondingly for R, the only way in which two elements can change their ordering relative to each other is for the greater one to appear in L and the lesser one to appear in R. Thus, there is at least one merge-inversion involving x and y. To see that there is exactly one such merge-inversion, observe that after any call of MERGE that involves both x and y, they are in the same sorted subarray and will therefore both appear in L or both appear in R in any given call thereafter. Thus, we have proven the claim.
算法导论 第三版 第23章 答案 英
Chapter23Michelle Bodnar,Andrew LohrApril12,2016Exercise23.1-1Suppose that A is an empty set of edges.Then,make any cut that has(u,v) crossing it.Then,since that edge is of minimal weight,we have that(u,v)is a light edge of that cut,and so it is safe to add.Since we add it,then,once wefinish constructing the tree,we have that(u,v)is contained in a minimum spanning tree.Exercise23.1-2Let G be the graph with4vertices:u,v,w,z.Let the edges of the graph be (u,v),(u,w),(w,z)with weights3,1,and2respectively.Suppose A is the set {(u,w)}.Let S=A.Then S clearly respects A.Since G is a tree,its minimum spanning tree is itself,so A is trivially a subset of a minimum spanning tree. Moreover,every edge is safe.In particular,(u,v)is safe but not a light edge for the cut.Therefore Professor Sabatier’s conjecture is false.Exercise23.1-3Let T0and T1be the two trees that are obtained by removing edge(u,v) from a MST.Suppose that V0and V1are the vertices of T0and T1respectively. Consider the cut which separates V0from V1.Suppose to a contradiction that there is some edge that has weight less than that of(u,v)in this cut.Then,we could construct a minimum spanning tree of the whole graph by adding that edge to T1∪T0.This would result in a minimum spanning tree that has weight less than the original minimum spanning tree that contained(u,v).Exercise23.1-4Let G be a graph on3vertices,each connected to the other2by an edge, and such that each edge has weight1.Since every edge has the same weight, every edge is a light edge for a cut which it spans.However,if we take all edges we get a cycle.1Exercise23.1-5Let A be any cut that causes some vertices in the cycle on once side of the cut,and some vertices in the cycle on the other.For any of these cuts,we know that the edge e is not a light edge for this cut.Since all the other cuts wont have the edge e crossing it,we won’t have that the edge is light for any of those cuts either.This means that we have that e is not safe.Exercise23.1-6Suppose that for every cut of the graph there is a unique light edge crossing the cut,but that the graph has2spanning trees T and T .Since T and T are distinct,there must exist edges(u,v)and(x,y)such that(u,v)is in T but not T and(x,y)is in T but not T.Let S={u,x}.There is a unique light edge which spans this cut.Without loss of generality,suppose that it is not(u,v). Then we can replace(u,v)by this edge in T to obtain a spanning tree of strictly smaller weight,a contradiction.Thus the spanning tree is unique.For a counter example to the converse,let G=(V,E)where V={x,y,z} and E={(x,y),(y,z),(x,z)}with weights1,2,and1respectively.The unique minimum spanning tree consists of the two edges of weight1,however the cut where S={x}doesn’t have a unique light edge which crosses it,since both of them have weight1.Exercise23.1-7First,we show that the subset of edges of minimum total weight that con-nects all the vertices is a tree.To see this,suppose not,that it had a cycle. This would mean that removing any of the edges in this cycle would mean that the remaining edges would still connect all the vertices,but would have a total weight that’s less by the weight of the edge that was removed.This would con-tradict the minimality of the total weight of the subset of vertices.Since the subset of edges forms a tree,and has minimal total weight,it must also be a minimum spanning tree.To see that this conclusion is not true if we allow negative edge weights,we provide a construction.Consider the graph K3with all edge weights equal to −1.The only minimum weight set of edges that connects the graph has total weight−3,and consists of all the edges.This is clearly not a MST because it is not a tree,which can be easily seen because it has one more edge than a tree on three vertices should have.Any MST of this weighted graph must have weight that is at least-2.Exercise23.1-8Suppose that L is another sorted list of edge weights of a minimum span-ning tree.If L =L,there must be afirst edge(u,v)in T or T which is of smaller weight than the corresponding edge(x,y)in the other set.Without2loss of generality,assume(u,v)is in T.Let C be the graph obtained by adding (u,v)to L .Then we must have introduced a cycle.If there exists an edge on that cycle which is of larger weight than(u,v),we can remove it to obtain a tree C of weight strictly smaller than the weight of T ,contradicting the fact that T is a minimum spanning tree.Thus,every edge on the cycle must be of lesser or equal weight than(u,v).Suppose that every edge is of strictly smaller weight.Remove(u,v)from T to disconnect it into two components.There must exist some edge besides(u,v)on the cycle which would connect these,and since it has smaller weight we can use that edge instead to create a spanning tree with less weight than T,a contradiction.Thus,some edge on the cycle has the same weight as(u,v).Replace that edge by(u,v).The corresponding lists L and L remain unchanged since we have swapped out an edge of equal weight, but the number of edges which T and T have in common has increased by1. If we continue in this way,eventually they must have every edge in common, contradicting the fact that their edge weights differ somewhere.Therefore all minimum spanning trees have the same sorted list of edge weights.Exercise23.1-9Suppose that there was some cheaper spanning tree than T .That is,we have that there is some T so that w(T )<w(T ).Then,let S be the edges in T but not in T .We can then construct a minimum spanning tree of G by considering S∪T .This is a spanning tree since S∪T is,and T makes all the vertices in V connected just like T does.However,we have that w(S∪T )=w(S)+w(T )<w(S)+w(T )=w(S∪T )=w(T).This means that we just found a spanning tree that has a lower total weight than a minimum spanning tree.This is a contradiction,and so our assumption that there was a spanning tree of V cheaper than T must be false.Exercise23.1-10Suppose that T is no longer a minimum spanning tree for G with edge weights given by w .Let T be a minimum spanning tree for this graph.Then we have we have w (T )<w(T)−k.Since the edge(x,y)may or may not be in T we have w(T )≤w (T )+k<w(T),contradicting the fact that T was minimal under the weight function w.Exercise23.1-11If we were to add in this newly decreased edge to the given tree,we would be creating a cycle.Then,if we were to remove any one of the edges along this cycle,we would still have a spanning tree.This means that we look at all the weights along this cycle formed by adding in the decreased edge,and remove the edge in the cycle of maximum weight.This does exactly what we want since we could only possibly want to add in the single decreased edge,and then,from there we change the graph back to a tree in the way that makes its total weight3minimized.Exercise23.2-1Suppose that we wanted to pick T as our minimum spanning tree.Then,to obtain this tree with Kruskal’s algorithm,we will order the edgesfirst by their weight,but then will resolve ties in edge weights by picking an edgefirst if it is contained in the minimum spanning tree,and treating all the edges that aren’t in T as being slightly larger,even though they have the same actual weight. With this ordering,we will still befinding a tree of the same weight as all the minimum spanning trees w(T).However,since we prioritize the edges in T,we have that we will pick them over any other edges that may be in other minimum spanning trees.Exercise23.2-2At each step of the algorithm we will add an edge from a vertex in the tree created so far to a vertex not in the tree,such that this edge has minimum weight.Thus,it will be useful to know,for each vertex not in the tree,the edge from that vertex to some vertex in the tree of minimal weight.We will store this information in an array A,where A[u]=(v,w)if w is the weight of(u,v) and is minimal among the weights of edges from u to some vertex v in the tree built so far.We’ll use A[u].1to access v and A[u].2to access w.Algorithm1PRIM-ADJ(G,w,r)Initialize A so that every entry is(NIL,∞)T={r}for i=1to V doif Adj[r,i]=0thenA[i]=(r,w(r,i))end ifend forfor each u∈V−T dok=min i A[i].2T=T∪{k}k.π=A[k].1for i=1to V doif Adj[k,i]=0and Adj[k,i]<A[i].2thenA[i]=(k,Adj[k,i])end ifend forend forExercise23.2-34Prim’s algorithm implemented with a Binary heap has runtime O((V+ E)lg(V)),which in the sparse case,is just O(V lg(V)).The implementation with Fibonacci heaps is O(E+V lg(V))=O(V+V lg(V))=O(V lg(V)).So, in the sparse case,the two algorithms have the same asymptotic runtimes.In the dense case,we have that the binary heap implementation has runtime O((V+E)lg(V))=O((V+V2)lg(V))=O(V2lg(V)).The Fibonacci heap implementation however has a runtime of O(E+V lg(V))=O(V2+V lg(V))= O(V2).So,in the dense case,we have that the Fibonacci heap implementation is asymptotically faster.The Fibonacci heap implementation will be asymptotically faster so long as E=ω(V).Suppose that we have some function that grows more quickly than linear,say f,and E=f(V).The binary heap implementation will have runtime O((V+E)lg(V))=O((V+f(V))lg(V))=O(f(V)lg(V)).However, we have that the runtime of the Fibonacci heap implementation will have run-time O(E+V lg(V))=O(f(V)+V lg(V)).This runtime is either O(f(V))or O(V lg(V))depending on if f(V)grows more or less quickly than V lg(V)re-spectively.In either case,we have that the runtime is faster than O(f(V)lg(V)).Exercise23.2-4If the edge weights are integers in the range from1to|V|,we can make Kruskal’s algorithm run in O(Eα(V))time by using counting sort to sort the edges by weight in linear time.I would take the same approach if the edge weights were integers bounded by a constant,since the runtime is dominated by the task of deciding whether an edge joins disjoint forests,which is independent of edge weights.Exercise23.2-5If there the edge weights are all in the range1,...,|V|,then,we can imagine adding the edges to an array of lists,where the edges of weight i go into the list in index i in the array.Then,to decrease an element,we just remove it from the list currently containing it(constant time)and add it to the list corresponding to its new value(also constant time).To extract the minimum wight edge,we maintain a linked list among all the indices that contain non-empty lists,which can also be maintained with only a constant amount of extra work.Since all of these operations can be done in constant time,we have a total runtime O(E+V).If the edge weights all lie in some bounded universe,suppose in the range 1to W.Then,we can just vEB tree structure given in chapter20to have the two required operations performed in time O(lg(lg(W))),which means that the total runtime could be made O((V+E)lg(lg(W))).Exercise23.2-6For input drawn from a uniform distribution I would use bucket sort with5Kruskal’s algorithm,for expected linear time sorting of edges by weight.This would achieve expected runtime O(Eα(V)).Exercise23.2-7Wefirst add all the edges to the new vertex.Then,we preform a DFS rooted at that vertex.As we go down,we keep track of the largest weight edge seen so far since each vertex above us in the DFS.We know from exercise23.3-6that in a directed graph,we don’t need to consider cross or forward edges.Every cycle that we detect will then be formed by a back edge.So,we just remove the edge of greatest weight seen since we were at the vertex that the back edge is going to.Then,we’ll keep going until we’ve removed one less than the degree of the vertex we added many edges.This will end up being linear time since we can reuse part of the DFS that we had already computed before detecting each cycle.Exercise23.2-8Professor Borden is mistaken.Consider the graph with4vertices:a,b,c, and d.Let the edges be(a,b),(b,c),(c,d),(d,a)with weights1,5,1,and5 respectively.Let V1={a,d}and V2={b,c}.Then there is only one edge incident on each of these,so the trees we must take on V1and V2consist of precisely the edges(a,d)and(b,c),for a total weight of10.With the addition of the weight1edge that connects them,we get weight11.However,an MST would use the two weight1edges and only one of the weight5edges,for a total weight of7.Problem23-1a.To see that the second best minimum spanning tree need not be unique,weconsider the following example graph on four vertices.Suppose the vertices are{a,b,c,d},and the edge weights are as follows:a b c da−143b1−52c45−6d326−Then,the minimum spanning tree has weight7,but there are two spanning trees of the second best weight,8.b.We are trying to show that there is a single edge swap that can demote ourminimum spanning tree to a second best minimum spanning tree.In obtaining the second best minimum spanning tree,there must be some cut of a single vertex away from the rest for which the edge that is added is not light,otherwise,we wouldfind the minimum spanning tree,not the second best minimum spanning tree.Call the edge that is selected for that cut for6the second best minimum spanning tree(x,y).Now,consider the same cut, except look at the edge that was selected when obtaining T,call it(u,v).Then,we have that if consider T−{(u,v)}∪{(x,y)},it will be a second best minimum spanning tree.This is because if the second best minimum spanning tree also selected a non-light edge for another cut,it would end up more expensive than all the minimum spanning trees.This means that we need for every cut other than the one that the selected edge was light.This means that the choices all align with what the minimum spanning tree was.c.We give here a dynamic programming solution.Suppose that we want tofind it for(u,v).First,we will identify the vertex x that occurs immediately after u on the simple path from u to v.We will then make max[u,v]equal to the max of w((u,x))and max[w,v].Lastly,we just consider the case that u and v are adjacent,in which case the maximum weight edge is just the single edge between the two.If we canfind x in constant time,then we will have the whole dynamic program running in time O(V2),since that’s the size of the table that’s being built up.Tofind x in constant time,we preprocess the tree.Wefirst pick an arbitrary root.Then,we do the preprocessing for Tarjan’s off-line least common an-cestors algorithm(See problem21-3).This takes time just a little more than linear,O(|V|α(|V|)).Once we’ve computed all the least common ancestors, we can just look up that result at some point later in constant time.Then, tofind the w that we should pick,wefirst see if u=LCA(u,v)if it does not,then we just pick the parent of u in the tree.If it does,then weflip the question on its head and try to compute max[v,u],we are guaranteed to not have this situation of v=LCA(v,u)because we know that u is an ancestor of v.d.We provide here an algorithm that takes time O(V2)and leave open if thereexists a linear time solution,that is a O(E+V)time solution.First,we find a minimum spanning tree in time O(E+V lg(V)),which is in O(V2).Then,using the algorithm from part c,wefind the double array max.Then, we take a running minimum over all pairs of vertices u,v,of the value of w(u,v)−max[u,v].If there is no edge between u and v,we think of the weight being infinite.Then,for the pair that resulted in the minimum value of this difference,we add in that edge and remove from the minimum spanning tree, an edge that is in the path from u to v that has weight max[u,v].Problem23-2a.We’ll show that the edges added at each step are safe.Consider an un-marked vertex u.Set S={u}and let A be the set of edges in the tree so far. Then the cut respects A,and the next edge we add is a light edge,so it is safe for A.Thus,every edge in T before we run Prim’s algorithm is safe for T.Any edge that Prim’s would normally add at this point would have to connect two7of the trees already created,and it would be chosen as minimal.Moreover,we choose exactly one between any two trees.Thus,the fact that we only have the smallest edges available to us is not a problem.The resulting tree must be minimal.b.We argue by induction on the number of vertices in G.We’ll assume that|V|>1,since otherwise MST-REDUCE will encounter an error on line6 because there is no way to choose v.Let|V|=2.Since G is connected,there must be an edge between u and v,and it is trivially of minimum weight.They are joined,and|G .V|=1=|V|/2.Suppose the claim holds for|V|=n.Let G be a connected graph on n+1vertices.Then G .V≤n/2prior to thefinal vertex v being examined in the for-loop of line4.If v is marked then we’re done, and if v isn’t marked then we’ll connect it to some other vertex,which must be marked since v is the last to be processed.Either way,v can’t contribute an additional vertex to G .V,so|G .V|≤n/2≤(n+1)/2.c.Rather than using the disjoint set structures of chapter21,we can simply use an array to keep track of which component a vertex is in.Let A be an array of length|V|such that A[u]=v if v=F IND−SET(u).Then FIND-SET(u) can now be replaced with A[u]and UNION(u,v)can be replaced by A[v]=A[u]. Since these operations run in constant time,the runtime is O(E).d.The number of edges in the output is monotonically decreasing,so each call is O(E).Thus,k calls take O(kE)time.e.The runtime of Prim’s algorithm is O(E+V lg V).Each time we run MST-REDUCE,we cut the number of vertices at least in half.Thus,af-ter k calls,the number of vertices is at most|V|/2k.We need to minimizeE+V/2k lg(V/2k)+kE=E+V lg(V)k −V kk+kE with respect to k.If we choosek=lg lg V then we achieve the overall running time of O(E lg lg V)as desired.To see that this value of k minimizes,note that the V k2k term is always less thanthe kE term since E≥V.As k decreases,the contribution of kE decreases,and the contribution of V lg V2k increases.Thus,we need tofind the value of kwhich makes them approximately equal in the worst case,when E=V.Todo this,we set lg V2k =k.Solving this exactly would involve the Lambert Wfunction,but the nicest elementary function which gets close is k=lg lg V.f.We simply set up the inequality E lg lg V<E+V lg V tofind that weneed E<V lg Vlg lg V−1=OV lg Vlg lg V.Problem23-3a.To see that every minimum spanning tree is also a bottleneck spanning tree.Suppose that T is a minimum spanning tree.Suppose there is some edge in it(u,v)that has a weight that’s greater than the weight of the bottleneck8spanning tree.Then,let V1be the subset of vertices of V that are reach-able from u in T,without going though v.Define V2symmetrically.Then, consider the cut that separates V1from V2.The only edge that we could add across this cut is the one of minimum weight,so we know that there are no edge across this cut of weight less than w(u,v).However,we have that there is a bottleneck spanning tree with less than that weight.This is a contradiction because a bottleneck spanning tree,since it is a spanning tree, must have an edge across this cut.b.To do this,wefirst process the entire graph,and remove any edges thathave weight greater than b.If the remaining graph is selected,we can just arbitrarily select any tree in it,and it will be a bottleneck spanning tree of weight at most b.Testing connectivity of a graph can be done in linear time by running a breadthfirst search and then making sure that no vertices remain white at the end.c.Write down all of the edge weights of e the algorithm from section9.3tofind the median of this list of numbers in time O(E).Then,run theprocedure from part b with this median value as the one that you are testing for there to be a bottleneck spanning tree with weight at most.Then there are two cases:First,we could have that there is a bottleneck spanning tree with weight at most this median.Then just throw the edges with weight more than the median,and repeat the procedure on this new graph with half the edges.Second,we could have that there is no bottleneck spanning tree with at most that weight.Then,we should run the procedure from problem23-2 to contract all of the edges that have weight at most this median weight.This takes time O(E lg(lg(V)))and then we are left solving the problem ona graph that now has half the vertices.Problem23-4a.This does return an MST.To see this,we’ll show that we never remove anedge which must be part of a minimum spanning tree.If we remove e,thene cannot be a bridge,which means that e lies on a simple cycle of the graph.Since we remove edges in nonincreasing order,the weight of every edge on the cycle must be less than or equal to that of e.By exercise23.1-5,there isa minimum spanning tree on G with edge e removed.To implement this,we begin by sorting the edges in O(E lg E)time.For each edge we need to check whether or not T−{e}is connected,so we’ll need to run a DFS.Each one takes O(V+E),so doing this for all edges takes O(E(V+E).This dominates the running time,so the total time is O(E2).9b.This doesn’t return an MST.To see this,let G be the graph on3verticesa,b,and c.Let the eges be(a,b),(b,c),and(c,a)with weights3,2,and1 respectively.If the algorithm examines the edges in their order listed,it will take the two heaviest edges instead of the two lightest.An efficient implementation will use disjoint sets to keep track of connected components,as in MST-REDUCE in problem23-2.Trying to union within the same component will create a cycle.Since we make|V|calls to MAKE-SET and at most3|E|calls to FIND-SET and UNION,the runtime is O(Eα(V)).c.This does return an MST.To see this,we simply quote the result from exer-cise23.1-5.The only edges we remove are the edges of maximum weight on some cycle,and there always exists a minimum spanning tree which doesn’t include these edges.Moreover,if we remove an edge from every cycle then the resulting graph cannot have any cycles,so it must be a tree.To implement this,we use the approach taken in part(b),except now we also need tofind the maximum weight edge on a cycle.For each edge which introduces a cycle we can perform a DFS tofind the cycle and max weight edge.Since the tree at that time has at most one cycle,it has at most|V| edges,so we can run DFS in O(V).The runtime is thus O(EV).10。
算法导论(第二版)课后习题解答
Θ
i=1
i
= Θ(n2 )
This holds for both the best- and worst-case running time. 2.2 − 3 Given that each element is equally likely to be the one searched for and the element searched for is present in the array, a linear search will on the average have to search through half the elements. This is because half the time the wanted element will be in the first half and half the time it will be in the second half. Both the worst-case and average-case of L INEAR -S EARCH is Θ(n). 3
Solutions for Introduction to algorithms second edition
Philip Bille
The author of this document takes absolutely no responsibility for the contents. This is merely a vague suggestion to a solution to some of the exercises posed in the book Introduction to algorithms by Cormen, Leiserson and Rivest. It is very likely that there are many errors and that the solutions are wrong. If you have found an error, have a better solution or wish to contribute in some constructive way please send a message to beetle@it.dk. It is important that you try hard to solve the exercises on your own. Use this document only as a last resort or to check if your instructor got it all wrong. Please note that the document is under construction and is updated only sporadically. Have fun with your algorithms. Best regards, Philip Bille
算法导论中文版答案
24.2-3
24.2-4
24.3-1 见图 24-6 24.3-2
24.3-3
24.3-4 24.3-5 24.3-6
24.3-7
24.3-8 这种情况下不会破坏已经更新的点的距离。 24.4**** 24.5****
25.1-1 见图 25-1 25.1-2 为了保证递归定义式 25.2 的正确性 25.1-3
8.3-3 8.3-4
8.3-5(*) 8.4-1 见图 8-4 8.4-2
8.4-3 3/2,1/2 8.4-4(*) 8.4-5(*)
9.1-1
9.1-2 9.2-1 9.3-1
第九章
9.3-2 9.3-3
9.3-4 9.3-5
9.3-6 9.3-7
9.3-8
9.3-9
15.1-1
6.4-4
6.4-5
6.5-1 据图 6-5 6.5-2
6.5-3 6.5-4 6.5-5
6.5-6 6.5-7
6.5-8
7.1-1 见图 7-1 7.1-2
7.1-3 7.1-4 7.2-1 7.2-2
7.2-3 7.2-4 7.2-5
第七章
7.2-6 7.3-1
7.3-2
7.4-1 7.4-2
5.3-6
6.1-1 6.1-2 6.1-3 6.1-4 6.1-5 6.1-6
第6章
6.1-7
6.2-1 见图 6-2 6.2-2
6.2-3
6.2-4
6.2-5 对以 i 为根结点的子树上每个点用循环语句实现 6.2-6
6.3-1
见图 6-3 6.3-2
6.3-3
6.4-1 见图 6-4 6.4-2 HEAPSORT 仍然正确,因为每次循环的过程中还是会运行 MAX-HEAP 的过程。 6.4-3
算法导论中文版答案
} cout<<len<<endl; } return 0; } 15.5-1
15.5-2 15.5-3
15.5-4
16.1-1
第 16 章
16.1-2 16.1-3
16.1-4 16.2-1 16.2-2
16.2-3
16.2-4
16.2-5 16.2-6
16.2-7
25.3-6
5.3-6
6.1-1 6.1-2 6.1-3 6.1-4 6.1-5 6.1-6
第6章
6.1-7
6.2-1 见图 6-2 6.2-2
6.2-3
6.2-4
6.2-5 对以 i 为根结点的子树上每个点用循环语句实现 6.2-6
6.3-1
见图 6-3 6.3-2
6.3-3
6.4-1 见图 6-4 6.4-2 HEAPSORT 仍然正确,因为每次循环的过程中还是会运行 MAX-HEAP 的过程。 6.4-3
6.4-4
6.4-5
6.5-1 据图 6-5 6.5-2
6.5-3 6.5-4 6.5-5
6.5-6 6.5-7
6.5-8
7.1-1 见图 7-1 7.1-2
7.1-3 7.1-4 7.2-1 7.2-2
7.2-3 7.2-4 7.2-5
第七章
7.2-6 7.3-1
7.3-2
7.4-1 7.4-2
16.3-1 16.3-2
16.3-3 16.3-4
16.3-5
16.3-6 那就推广到树的结点有三个孩子结点,证明过程同引理 16.3 的证明。 16.3-7 16.3-8
第 24 章
24.1-1 同源顶点 s 的运行过程,见图 24-4 24.1-2