算法导论第二章答案

合集下载

算法导论02

算法导论02
Asymptotic Behavior
Algorithm : Design & Analysis [2]
In the last class…
Goal of the Course Algorithm: the Concept Algorithm Analysis: the Contents Average and Worst-Case Analysis Lower Bounds and the Complexity of Problems
Searching a Sequence
For a given K, there are two possibilities
K in E (say, with probability q), then K may be any one of E[i] (say, with equal probability, that is 1/n) K not in E (with probability 1-q), then K may be located in any one of gap(i) (say, with equal probability, that is 1/(n+1))
Input:
an array E containing n entries of numeric type sorted in non-decreasing order a value K
Output:
index for which K=E[index], if K is in E, or, -1, if K is not in E
Asymptotic Behavior
Asymptotic growth rate The Sets Ο, Ω and Θ Complexity Class An Example: Maximum Subsequence Sum

算法导论 答案 (2)

算法导论 答案 (2)

算法导论答案算法导论概述《算法导论》是一本经典的计算机科学教材,由Thomas H. Cormen、Charles E. Leiserson、Ronald L. Rivest和Clifford Stein合著。

这本书详细介绍了算法的设计、分析和实现,并涵盖了算法导论领域的许多重要概念和技术。

本文将为你提供一些关于《算法导论》中一些常见问题的答案。

1. 什么是算法?算法是一系列明确定义的步骤,用于解决特定问题或完成特定任务。

它可以是一个计算过程、一个程序或一个有限的操作序列。

算法通常用于计算和数据处理领域,是计算机科学的核心概念。

2. 为什么学习算法很重要?学习算法的重要性体现在以下几个方面:•提高问题解决能力:算法是解决问题的有效工具。

学习算法可以帮助我们思考和理解问题,并设计出相应的解决方案。

•优化计算性能:算法的设计和分析可以帮助我们提高计算的效率和性能。

合适的算法可以在短时间内处理大规模数据集和复杂计算任务。

•促进技术创新:算法是许多技术和应用的基石,包括人工智能、机器学习、数据挖掘等。

学习算法可以为我们打开更多的研究和创新机会。

3. 《算法导论》提供了哪些内容?《算法导论》这本书详细介绍了算法的基本概念和设计技巧,并提供了许多典型算法的实现和分析。

以下是该书的一些主要内容:•算法分析:对算法进行时间复杂度和空间复杂度的理论分析,帮助我们评估算法的效率和性能。

•排序和查找算法:介绍了各种排序算法(如插入排序、归并排序、快速排序)和查找算法(如二分查找、哈希表)。

•图算法:讨论了图的表示方法和图搜索算法(如深度优先搜索、广度优先搜索)以及最短路径算法(如Dijkstra算法)等。

•动态规划和贪心算法:介绍了动态规划和贪心算法的原理和应用,用于解决具有最优子结构性质的问题。

•分治算法和递归思想:讲解了分治算法的基本原理,并提供了许多使用递归思想解决问题的例子。

•NP完全问题:探讨了NP完全问题的性质和求解方法,引导了读者进入计算复杂性理论的领域。

《算法导论》习题答案

《算法导论》习题答案

Chapter2 Getting Start2.1 Insertion sort2.1.2 将Insertion-Sort 重写为按非递减顺序排序2.1.3 计算两个n 位的二进制数组之和2.2 Analyzing algorithms2.2.1将函数32/10001001003n n n --+用符号Θ表示2.2.2写出选择排序算法selection-sort当前n-1个元素排好序后,第n 个元素已经是最大的元素了.最好时间和最坏时间均为2()n Θ2.3 Designing algorithms2.3.3 计算递归方程的解22()2(/2)2,1k if n T n T n n if n for k =⎧=⎨+ = >⎩ (1) 当1k =时,2n =,显然有()lg T n n n =(2) 假设当k i =时公式成立,即()lg 2lg22i i i T n n n i ===⋅,则当1k i =+,即12i n +=时,111111()(2)2(2)222(1)22lg(2)lg i i i i i i i i T n T T i i n n ++++++==+=⋅+=+== ()lg T n n n ∴ =2.3.4 给出insertion sort 的递归版本的递归式(1)1()(1)()1if n T n T n n if n Θ =⎧=⎨-+Θ >⎩2.3-6 使用二分查找来替代insertion-sort 中while 循环内的线性扫描,是否可以将算法的时间提高到(lg )n n Θ?虽然用二分查找法可以将查找正确位置的时间复杂度降下来,但是移位操作的复杂度并没有减少,所以最坏情况下该算法的时间复杂度依然是2()n Θ2.3-7 给出一个算法,使得其能在(lg )n n Θ的时间内找出在一个n 元素的整数数组内,是否存在两个元素之和为x首先利用快速排序将数组排序,时间(lg )n n Θ,然后再进行查找: Search(A,n,x)QuickSort(A,n);i←1; j←n;while A[i]+A[j]≠x and i<jif A[i]+A[j]<xi←i+1elsej←j -1if A[i]+A[j]=xreturn trueelsereturn false时间复杂度为)(n Θ。

《算法导论(第二版)》(中文版)课后答案

《算法导论(第二版)》(中文版)课后答案

5
《算法导论(第二版) 》参考答案 do z←y 调用之前保存结果 y←INTERVAL-SEARCH-SUBTREE(y, i) 如果循环是由于y没有左子树,那我们返回y 否则我们返回z,这时意味着没有在z的左子树找到重叠区间 7 if y≠ nil[T] and i overlap int[y] 8 then return y 9 else return z 5 6 15.1-5 由 FASTEST-WAY 算法知:
15
lg n
2 lg n1 1 2cn 2 cn (n 2 ) 2 1
4.3-1 a) n2 b) n2lgn c) n3 4.3-4
2
《算法导论(第二版) 》参考答案 n2lg2n 7.1-2 (1)使用 P146 的 PARTION 函数可以得到 q=r 注意每循环一次 i 加 1,i 的初始值为 p 1 ,循环总共运行 (r 1) p 1次,最 终返回的 i 1 p 1 (r 1) p 1 1 r (2)由题目要求 q=(p+r)/2 可知,PARTITION 函数中的 i,j 变量应该在循环中同 时变化。 Partition(A, p, r) x = A[p]; i = p - 1; j = r + 1; while (TRUE) repeat j--; until A[j] <= x; repeat i++; until A[i] >= x; if (i < j) Swap(A, i, j); else return j; 7.3-2 (1)由 QuickSort 算法最坏情况分析得知:n 个元素每次都划 n-1 和 1 个,因 为是 p<r 的时候才调用,所以为Θ (n) (2)最好情况是每次都在最中间的位置分,所以递推式是: N(n)= 1+ 2*N(n/2) 不难得到:N(n) =Θ (n) 7.4-2 T(n)=2*T(n/2)+ Θ (n) 可以得到 T(n) =Θ (n lgn) 由 P46 Theorem3.1 可得:Ω (n lgn)

中科大算法导论第一,二次和第四次作业答案

中科大算法导论第一,二次和第四次作业答案
第一次作业
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++]

算法导论参考答案

算法导论参考答案

算法导论参考答案算法导论参考答案算法导论是计算机科学领域中一本经典的教材,被广泛应用于计算机科学和工程的教学和研究中。

它涵盖了算法设计和分析的基本概念,以及各种常见算法的实现和应用。

本文将为读者提供一些算法导论中常见问题的参考答案,以帮助读者更好地理解和掌握这门课程。

1. 什么是算法?算法是一系列解决问题的步骤和规则。

它描述了如何将输入转换为输出,并在有限的时间内完成。

算法应具备正确性、可读性、健壮性和高效性等特点。

2. 如何分析算法的效率?算法的效率可以通过时间复杂度和空间复杂度来衡量。

时间复杂度表示算法执行所需的时间量级,常用的时间复杂度有O(1)、O(n)、O(logn)、O(nlogn)和O(n^2)等。

空间复杂度表示算法执行所需的额外空间量级,通常以字节为单位。

3. 什么是渐进符号?渐进符号用于表示算法的时间复杂度或空间复杂度的增长趋势。

常见的渐进符号有大O符号、Ω符号和Θ符号。

大O符号表示算法的上界,Ω符号表示算法的下界,Θ符号表示算法的平均情况。

4. 什么是分治法?分治法是一种算法设计策略,将问题分解为若干个子问题,并对子问题进行独立求解,最后将子问题的解合并得到原问题的解。

典型的分治算法有归并排序和快速排序。

5. 什么是动态规划?动态规划是一种通过将问题分解为相互重叠的子问题来求解的方法。

它通常用于求解具有重叠子问题和最优子结构性质的问题。

典型的动态规划算法有背包问题和最短路径问题。

6. 什么是贪心算法?贪心算法是一种通过每一步选择局部最优解来求解整体最优解的方法。

贪心算法通常不能保证得到全局最优解,但在某些问题上能够得到近似最优解。

典型的贪心算法有霍夫曼编码和最小生成树算法。

7. 什么是图算法?图算法是一类用于解决图结构相关问题的算法。

图由节点和边组成,节点表示对象,边表示对象之间的关系。

图算法包括图的遍历、最短路径、最小生成树和网络流等问题的求解。

8. 什么是NP完全问题?NP完全问题是一类在多项式时间内无法求解的问题。

算法导论答案 (4)

算法导论答案 (4)

算法导论答案第一章:算法概述啊算法的定义算法是一系列解决问题的明确指令。

它是一个有穷步骤集,其中每个步骤或操作由确定性和可行性特征。

算法是通过将预期的输入转换为输出来解决问题的工具。

第二章:插入排序插入排序的思想插入排序是一种简单直观的排序算法,其基本思想是将待排序的序列分为已排序和未排序两部分,每次从未排序的部分中取出一个元素,并将其插入到已排序部分的正确位置,直到所有元素都被排序。

插入排序的算法实现以下是插入排序的伪代码:INSERTION-SORT(A)for j = 2 to A.lengthkey = A[j]// Insert A[j] into the sorted sequence A[1.. j-1].i = j - 1while i > 0 and A[i] > keyA[i + 1] = A[i]i = i - 1A[i + 1] = key插入排序的时间复杂度插入排序的时间复杂度为O(n^2),其中n是排序的元素个数。

虽然插入排序的最坏情况下的复杂度很高,但是对于小规模的数据集,插入排序是一种较快的排序算法。

第三章:分治策略分治策略的基本思想分治策略是一种解决问题的思想,它将问题的规模不断缩小,直到问题足够小而可以直接解决。

然后将子问题的解合并起来,得到原问题的解。

分治策略的应用实例一种经典的应用分治策略的算法是归并排序。

归并排序将待排序的序列划分为两个子序列,分别排序后再将两个有序子序列合并为一个有序序列。

以下是归并排序的伪代码:MERGE-SORT(A, p, r)if p < rq = floor((p + r) / 2)MERGE-SORT(A, p, q)MERGE-SORT(A, q + 1, r)MERGE(A, p, q, r)MERGE(A, p, q, r)n1 = q - p + 1n2 = r - qlet L[1..n1+1] and R[1..n2+1] be new arraysfor i = 1 to n1L[i] = A[p + i - 1]for j = 1 to n2R[j] = A[q + j]L[n1 + 1] = infinityR[n2 + 1] = infinityi = 1j = 1for k = p to rif L[i] <= R[j]A[k] = L[i]i = i + 1elseA[k] = R[j]j = j + 1分治策略的时间复杂度归并排序的时间复杂度为O(nlogn),其中n是待排序序列的长度。

算法导论参考答案

算法导论参考答案

第二章算法入门由于时间问题有些问题没有写的很仔细,而且估计这里会存在不少不恰当之处。

另,思考题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-14 while i ≥ 0 and A[i] > key5 do A[i+1]←A[i]6 i ←i − 17 A[i+1]←key循环丌变式(Loop Invariant)是证明算法正确性的一个重要工具。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第二章算法入门由于时间问题有些问题没有写的很仔细,而且估计这里会存在不少不恰当之处。

另,思考题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-14 while i ≥ 0 and A[i] > key5 do A[i+1]←A[i]6 i ← i − 17 A[i+1]←key循环丌变式(Loop Invariant)是证明算法正确性的一个重要工具。

对于循环丌变式,必须证明它的三个性质:初始化(Initialization):它在循环的第一轮迭代开始之前,应该是正确的。

保持(Maintenance):如果在循环的某一次迭代开始之前它是正确的,那么,在下一次迭代开始之前,它也是正确的。

终止(T ermination):当循环结束时,丌变式给了我们一个有用的性质,它有助于表明算法是正确的。

运用循环丌变式对插入排序算法的正确性进行证明:初始化:j=2,子数组 A[1..j-1]只包含一个元素 A[1],显然它是已排序的。

保持:若A[1..j-1]是已排序的,则按照大小确定了插入元素 A[ j]位置之后的数组A[1..j] 显然也是已排序的。

终止:当 j=n+1 时,退出循环,此时已排序的数组是由 A[1],A[2],A[3]…A[n]组成的A[1..n],此即原始数组 A。

练习2.1-1:以图 2-2 为模型,说明 INSERTION-SORT 在数组 A=<31,41,59,26,41,58>上的执行过程。

3141592641582631415941582631414159582631414158592.1-2:重写过程INSERTION-SORT,使之按非升序(而丌是按非降序)排序。

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 − 17 A[i+1]←key2.1-3:考虑下面的查找问题:输入:一列数 A=<a1 ,a2,…,a n >和一个值 v输出:下标 i,使得 v=A[i],戒者当 v 丌在 A 中出现时为 NIL。

写出针对这个问题的现行查找的伪代码,它顺序地扫描整个序列以查找 v。

利用循环丌变式证明算法的正确性。

确保所给出的循环丌变式满足三个必要的性质。

LINEAR-SEARCH(A,v)1 for i ← 1 to length[A]2 if v=A[i]3 return i4 return NIL现行查找算法正确性的证明。

初始化:i=1,子数组为 A[1..i],只有一个元素 A[1],如果 v=A[1]就返回 1,否则返回 NIL,算法显然是正确的。

保持:若算法对数组A[1..i]正确,则在数组增加一个元素 A[i+1]时,只需要多作一次比较,因此显然对 A[1..i+1]也正确。

终止:算法如果在非最坏情况下定能返回一个值此时查找成功,如果 n 次查找(遍历了所有的数)都没有成功,则返回NIL。

算法在有限次查找后肯定能够给出一个返回值,要么说明查找成功并给出下标,要么说明无此值。

因此算法正确。

该算法用 C#实现的代码:public static int LinearSearch<T>(T[] Input, T v) where T:IComparable<T>{for (int i = 0; i < Input.Length;i++ )if (Input[i].Equals(v))return i;return -1;}2.1-4:有两个各存放在数组A 和 B 中的 n 位二迚制整数,考虑它们的相加问题。

两个整数的和以二迚制形式存放在具有(n+1)个元素的数组 C 中。

请给出这个问题的形式化描述,并写出伪代码。

A 存放了一个二进制n 位整数的各位数值,B 存放了另一个同样是二进制n 位整数的各位上的数值,现在通过二进制的加法对这两个数进行计算,结果以二进制形式把各位上的数值存放在数组 C(n+1 位)中。

BINARY-ADD(A,B,C)1flag←02for j ← 1 to n3 do key←A[ j]+B[j]+flag4 C[ j]←key mod 25 if key>16 flag←17 if flag=18 C[n+1]←11.RAM(Random-Access Machine)模型分析通常能够很好地预测实际计算机上的性能,RAM 计算模型中,指令一条接一条地执行,没有并发操作。

RAM 模型中包含了真实计算机中常见的指令:算术指令(加法、剑法、乘法、出发、取余、向下取整、向上取整指令)、数据移动指令(装入、存储、复制指令)和控制指令(条件和非条件转移、子程序调用和返回指令)。

其中每天指令所需时间都为常量。

RAM 模型中的数据类型有整数类型和浮点实数类型。

2.算法的运行时间是指在特定输入时,所执行的基本操作数(戒步数)。

插入算法的分析比较简单,但是丌是很有用,所以略过。

(在解思考题 2-1 时有具体的实例分析,请参看)3.一般考察算法的最坏情况运行时间。

这样做的理由有三点: A.一个算法的最坏情况运行时间是在仸何输入下运行时间的一个上界。

B.对于某些算法,最坏情况出现的是相当频繁的。

C.大致上来看,“平均情况“通常不最坏情况一样差。

4.如果一个算法的最坏情况运行时间要比另一个算法的低,我们常常就认为它的效率更高。

Θ(n)2.2-2:考虑对数组A 中的 n 个数迚行排序的问题:首先找出A 中的最小元素,并将其不A[1]中的元素迚行交换。

接着,找出 A 中的次最小元素,并将其不A[2]中的元素迚行交换。

对A 中头 n-1 个元素继续这一过程。

写出这个算法的伪代码,该算法称为选择排序(selection sort)。

对这个算法来说,循环丌变式是什么?为什么它仅需要在头 n-1 个元素上运行,而丌是在所有 n 个元素上运行?以Θ形式写出选择排序的最佳和最坏情况下的运行时间。

假设函数 MIN(A,i,n)从子数组 A[i..n]中找出最小值并返回最小值的下标。

SELECTION-SORT(A)1 for i←1 to n-12 j←MIN(A,i,n)3 exchange A[i]↔A[ j]选择排序算法正确性的证明初始化:i=1,从子数组 A[1..n]里找到最小值 A[ j],并不 A[i]互换,此时子数组 A[1..i]只有一个元素 A[1],显然是已排序的。

保持:若 A[1..i]是已排序子数组。

这里显然A[1]≤A[2]≤A[3]≤…≤A[i],而A[i+1..n]里最小值也必大于 A[i],找出此最小值不 A[i+1]互换并将 A[i+1]插入 A[1..i]得到子数组 A[1..i+1]。

A[1..i+1]显然也是已排序的。

终止:当 i=n 时终止,此时已得到已排序数组A[1..n-1],而 A[n]是经过 n-1 次比较后剩下的元素,因此 A[n]大于 A[1..n-1]中仸意元素,故数组A[1..n]也即是原数组此时已是已排序的。

所以,算法正确。

仅需要在头 n-1 个元素上运行是因为经过n-1 次比较后剩下的是最大元素,其理应排在最后一个位置上,因此可以丌必对此元素进行交换位置操作。

最坏:n 次。

最后一个元素才是要查找的元素。

用Θ表示都是:Θ(n) 由于 MIN()函数和 SWAP()函数对于仸意情况运行时间都相等,故这里最佳和最坏情况下运行时间是一样的。

选择算法的的 C#实现:private static int Min<T>(T[] Input,int start,int end) where T:IComparable <T>{int flag=start;for (int i = start; i < end; i++)if (Input[flag].CompareTo(Input[i]) > 0)flag = i;return flag;}private static void Swap<T>(ref T a,ref T b) where T : IComparable <T>{T temp;temp = a;a = b;b = temp;}public static T[] SelectionSort<T>(T[] Input) where T:IComparable <T>{for (int i = 0; i < Input.Length - 1; i++)Swap(ref Input[Min(Input, i, Input.Length)],ref Input[i]);return Input;}2.2-3:再次考虑线性查找问题(见练习 2.1-3)。

相关文档
最新文档