用分治法解决问题
分治法的简单描述

分治法的简单描述分治法是一种算法设计的思想,它将一个大问题分解为多个小问题,通过解决小问题来解决大问题。
这种思想的应用非常广泛,可以用来解决各种问题,比如排序、查找、计算等等。
下面我们来详细介绍一下分治法的基本原理和应用。
分治法的基本原理是将一个问题分解为多个独立的子问题,然后对每个子问题进行求解,最后将子问题的解合并起来得到原问题的解。
这种分解和合并的过程可以递归地进行,直到问题变得足够简单,可以直接求解为止。
在应用分治法解决问题时,需要满足以下三个条件:1.原问题可以分解为多个独立的子问题;2.子问题的结构与原问题相同,只是规模更小;3.子问题的解可以合并得到原问题的解。
接下来我们来看两个分治法的经典应用:归并排序和快速排序。
归并排序是一种经典的排序算法,它的基本思想就是使用分治法将一个无序的序列分解为多个有序的子序列,然后再将这些子序列合并起来得到一个有序的序列。
具体的步骤如下:1.将序列分成两个子序列,分别对这两个子序列进行归并排序;2.将两个有序的子序列合并成一个有序的序列。
归并排序的时间复杂度为O(nlogn),其中n是序列的长度。
它的空间复杂度为O(n),其中n是序列的长度。
快速排序是另一种经典的排序算法,它的基本思想也是使用分治法将一个无序的序列分解为多个有序的子序列,然后再将这些子序列合并起来得到一个有序的序列。
具体的步骤如下:1.从序列中选择一个元素作为基准值,将序列分成两个子序列,一个小于基准值,一个大于基准值;2.分别对这两个子序列进行快速排序;3.将两个有序的子序列合并成一个有序的序列。
快速排序的时间复杂度取决于基准值的选择,最坏情况下的时间复杂度为O(n^2),其中n是序列的长度。
但是平均情况下的时间复杂度为O(nlogn),空间复杂度为O(logn)。
除了排序问题,分治法还可以应用于其他一些问题,比如最大子数组和问题。
给定一个整数数组,找到一个具有最大和的连续子数组。
分治法解决问题的步骤

分治法解决问题的步骤一、基础概念类题目(1 - 5题)题目1:简述分治法解决问题的基本步骤。
解析:分治法解决问题主要有三个步骤:1. 分解(Divide):将原问题分解为若干个规模较小、相互独立且与原问题形式相同的子问题。
例如,对于排序问题,可将一个大的数组分成两个较小的子数组。
2. 求解(Conquer):递归地求解这些子问题。
如果子问题规模足够小,则直接求解(通常是一些简单的基础情况)。
对于小到只有一个元素的子数组,它本身就是有序的。
3. 合并(Combine):将各个子问题的解合并为原问题的解。
在排序中,将两个已排序的子数组合并成一个大的有序数组。
题目2:在分治法中,分解原问题时需要遵循哪些原则?解析:1. 子问题规模更小:分解后的子问题规模要比原问题小,这样才能逐步简化问题。
例如在归并排序中,不断将数组对半分,子数组的长度不断减小。
2. 子问题相互独立:子问题之间应该尽量没有相互依赖关系。
以矩阵乘法的分治算法为例,划分后的子矩阵乘法之间相互独立进行计算。
3. 子问题与原问题形式相同:方便递归求解。
如二分查找中,每次查找的子区间仍然是一个有序区间,和原始的有序区间查找问题形式相同。
题目3:分治法中的“求解”步骤,如果子问题规模小到什么程度可以直接求解?解析:当子问题规模小到可以用简单的、直接的方法(如常量时间或线性时间复杂度的方法)解决时,就可以直接求解。
例如,在求数组中的最大最小值问题中,当子数组只有一个元素时,这个元素既是最大值也是最小值,可以直接得出结果。
题目4:分治法的“合并”步骤有什么重要性?解析:1. 构建完整解:它将各个子问题的解组合起来形成原问题的解。
例如在归并排序中,单独的两个子数组排序好后,只有通过合并操作才能得到整个数组的有序排列。
2. 保证算法正确性:如果合并步骤不正确,即使子问题求解正确,也无法得到原问题的正确答案。
例如在分治算法计算斐波那契数列时,合并不同子问题的结果来得到正确的斐波那契数是很关键的。
简述分治法求解的基本步骤

简述分治法求解的基本步骤分治法是一种基本的求解算法,它可以帮助我们解决复杂问题并实现高效的解决方案。
简言之,分治法是一个非常强大的算法,可以帮助我们解决很多规模较大的复杂问题。
分治法是由三个基本步骤组成:分解、解决和结合。
首先,分解步骤是分治法的核心步骤,即将原问题划分为若干规模较小的子问题,以便进行求解。
这些子问题往往容易解决,而且与原问题有联系。
比如,在解决一个最大的问题的时候,可以分解为N 个子问题,每个子问题都可以轻松解决。
其次,解决步骤则是对这些已经分解的子问题求解。
决定求解哪种子问题,则取决于实际情况,最常用的也有暴力解法、递归法、动态规划法等。
如果每个子问题都可以得到一个最优解,那么分治法也可以求出原问题的最优解。
最后,结合步骤是将分解出来的子问题的解合并成原问题的解。
一般来说,如果子问题的解是一个最优解的集合,则可以将这些最优解合并成原问题的最优解。
有时候,我们也可以从子问题的最优解中构造出一个更优解用于满足原问题。
总结起来,分治法求解的基本步骤由分解、解决和结合三个基本步骤组成,其中,分解步骤是分治法的核心步骤,解决步骤是求解已经分解的子问题,结合步骤是将子问题的解合并成原问题的解。
在解决复杂问题的时候,分治法可以极大的提高算法的效率,并且简单易行,非常实用。
分治法在计算机科学中被广泛使用,它可以解决多种不同的问题,包括排序、搜索、图论、博弈、动态规划、最大流量问题等。
分治法可以大大提高算法的运行效率,使得解决复杂问题更加便捷。
因此,分治法是一种非常有效的算法,近年来得到了越来越多的应用。
综上所述,分治法是一种有效的算法,它可以帮助我们解决复杂的问题并得到最优解,它由三个基本步骤组成:分解、解决和结合。
在解决复杂问题的时候,应用分治法可以大大提高算法的效率,已较好地解决问题。
分治法解决集合划分问题

T(n/4)
T(n/4)
将求出的小规模的问题的解合并为一个更 大规模的问题的解,自底向上逐步求出原 来问题的解。
T(n)
T(n/2)
T(n/2)
T(n/4)
T(n/4)
T(n/4)
T(n/4)
将求出的小规模的问题的解合并为一个更 大规模的问题的解,自底向上逐步求出原 来问题的解。
T(n)
T(n/2)
2、 分治法就是为解决大规模问题而提出的 将要求解的大规模的问题分解为k个较 小规模的问题,对这k个子问题分别求解。
T(n)
T(n/2)
T(n/2)
如果子问题的规模仍然不够小,则再划分 为k个子问题,如此递归的进行下去,直到 问题规模足够小,很容易求出其解为止。
T(n)
T(n/2)
T(n/4)
T(n/4)
③ 3个子集的集合:{{1},{2},{3}} f(m,n)=? 显然 f(3,1)=1; f(3,2)=3; f(3,3)=1;
如果要求f(4,2)该怎么办呢? A.往①里添一个元素{4},得到{{1,2,3}, {4}} B.往②里的任意一个子集添一个4,得到 {{1,2,4},{3}},{{1,2},{3,4}}, {{1,3,4},{2}},{{1,3},{2,4}}, {{2,3,4},{1}},{{2,3},{1,4}} ∴f(4,2)=f(3,1)+2*f(3,2)=1+2*3=7
递归举例 0 n=0
边界条件
n!=
n (n-1)! n > 0
递归方程
边界条件与递归方程是递归函数的二 个要素,递归函数只有具备了这两个 要素,才能在有限次计算后得出结果。
4、要解决的问题 给定正整数m和n,计算出m 个元素的集合 {1,2,., m}可以划分为多少个不同的由n 个 非空子集组成的集合。
分治法解决大整数乘法问题

分治法解决大整数乘法问题通常,在分析算法的计算复杂性时,都将加法和乘法运算当作基本运算来处理,即将执行一次加法或乘法运算所需的计算时间,当作一个仅取决于计算机硬件处理速度的常数。
这个假定仅在参加运算的整数能在计算机硬件对整数的表示范围内直接处理才是合理的。
然而,在某些情况下,要处理很大的整数,它无法在计算机硬件能直接表示的整数范围内进行处理。
若用浮点数来表示它,则只能近似的表示它的大小,计算结果中的有效数字也受到限制。
若要精确地表示大整数并在计算结果中要求精确地得到所有位数上的数字,就必须用软件的方法来实现大整数的算术运算。
设X和Y都是n位的二进制整数,现在要计算它们的乘积Z。
可以用小学所学的方法来设计计算乘积XY的算法,但是这样做计算步骤太多,效率较低。
如果将每2个1位数的乘法或加法看作一步运算,那么这种方法要进行O(n^2)步运算才能算出乘积XY。
下面用分治法来设计更有效的大整数乘积算法。
将n位二进制数X和Y都分为两段,每段长n/2位(为简单起见,假设n是2的幂)。
则有:其中X1、Xo分别为X的高位和低位,Y1、Yo分别为Y 的高位和低位。
C2是它们的前半部分的积;Co是它们后半部分的积;C1是X、Y两部分的和的积减去C2与C0的积。
如果n/2也是偶数,我们可以利用相同的方法来计算C2、Co 的和C1。
因此我们就得到了一个计算n位数积的递归算法:在这种完美的形式下,当n变成1时,递归就停止了.或者当我们认为n已经够小了,小到可以直接对这样大小的数相乘时,递归就可以停止了.该算法会有多少次位乘呢?因为n位数的乘法需要对n/2位数做三次乘法运算,乘法次数M(n)的递推式将会是:当n>1时,M(n)=3M(n/2),M(1)=1当n=2^k时,我们可以用反向替换法对它求解:因为所以在最后一步中,我们利用了对数的一个特性:我们应当知道对于不是很大的数,该算法的运行时间很可能比经典算法长.有报告显示,从大于600位的整数开始,分治法的性能超越了笔算算法的性能.如果我们使用类似Java、C++和Smalltalk这样的面向对象语言,会发现这些语言专门为处理大整数提供了一些类。
蛮力法、分治法、减治法三种方法的理解和处理问题的类型的归纳

蛮力法、分治法、减治法三种方法的理解和处理问题的类型的归纳一、蛮力法蛮力法是一种基础且直接的问题解决策略,通常用于寻找问题的答案或解决方案。
其核心理念在于,通过逐一检查所有可能的解决方案,从而找到问题的答案或找到最佳的解决方案。
在蛮力法中,我们通常需要投入较多的时间和计算资源,尤其是在面对大规模或复杂的问题时。
蛮力法的应用范围广泛,包括但不限于以下几种类型的问题:1. 排序问题:例如,对一个数组进行排序,我们可以使用蛮力法,通过比较每对元素并交换它们的位置,使得整个数组有序。
2. 查找问题:例如,在排序数组中查找一个特定的元素,我们可以使用蛮力法,逐一检查数组中的每个元素直到找到目标元素。
3. 组合与排列问题:例如,计算给定集合的所有可能排列或组合,我们可以使用蛮力法,通过逐一排列或组合所有可能的元素组合得到答案。
二、分治法分治法是一种将复杂问题分解为更小、更易于处理的子问题的方法。
通过将问题分解为独立的子问题,我们可以分别解决每个子问题,然后将这些解决方案组合起来,形成原始问题的解决方案。
这种方法在处理复杂问题时非常有效,因为它可以降低问题的复杂性,使我们可以更有效地解决问题。
分治法的应用范围广泛,包括但不限于以下几种类型的问题:1. 排序问题:例如,归并排序就是一种使用分治法的排序算法,它将一个大列表分解为两个小列表,对这两个小列表分别进行排序,然后合并它们以得到有序列表。
2. 搜索问题:例如,二分搜索是一种使用分治法的搜索算法,它将搜索空间一分为二,每次迭代都排除一半的元素,直到找到目标元素或确定元素不存在。
3. 图问题:例如,Dijkstra的算法就是一种使用分治法的图搜索算法,它将图分解为最短路径树,然后通过搜索每个子图的最短路径来解决整个图的最短路径问题。
三、减治法减治法是一种通过减少问题的规模或复杂性来解决问题的方法。
其核心理念在于,通过消除或减少问题的某些部分或特性,从而降低问题的复杂性或规模,使得问题更容易解决。
分治法的特征

分治法的特征:
分治法所能解决的问题一般具有以下几个特征:
1) 该问题的规模缩小到一定的程度就可以容易地解决
2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
3) 利用该问题分解出的子问题的解可以合并为该问题的解;
4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;
第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用;、
第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。
第四条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。
用分治法解决最近点对问题:python实现

⽤分治法解决最近点对问题:python实现 最近点对问题:给定平⾯上n个点,找其中的⼀对点,使得在n个点的所有点对中,该点对的距离最⼩。
需要说明的是理论上最近点对并不⽌⼀对,但是⽆论是寻找全部还是仅寻找其中之⼀,其原理没有区别,仅需略作改造即可。
本⽂提供的算法仅寻找其中⼀对。
解决最近点对问题最简单的⽅法就是穷举法,这样时间复杂度是平⽅级,可以说是最坏的策略。
如果使⽤分治法,其时间复杂度就是线性对数级,这样⼤⼤提⾼了效率。
⾸先⽤分治法解决该问题的基本思路可以参考 /lishuhuakai/article/details/9133961 ,说的很详细,但⼤致思路就是先根据x轴把所有点平分,然后分别在每⼀部分寻找最近点对,最后通过⽐较选⼀个最⼩的。
当然其中最核⼼的地⽅是跨域求距离,原⽂写的很清楚,在此就不再赘述了。
以下是代码:from math import sqrtdef nearest_dot(s):len = s.__len__()left = s[0:len/2]right = s[len/2:]mid_x = (left[-1][0]+right[0][0])/2.0if left.__len__() > 2: lmin = nearest_dot(left) #左侧部分最近点对else: lmin = leftif right.__len__() > 2: rmin = nearest_dot(right) #右侧部分最近点对else: rmin = rightif lmin.__len__() >1: dis_l = get_distance(lmin)else: dis_l = float("inf")if rmin.__len__() >1: dis_2 = get_distance(rmin)else: dis_2 = float("inf")d = min(dis_l, dis_2) #最近点对距离mid_min=[]for i in left:if mid_x-i[0]<=d : #如果左侧部分与中间线的距离<=dfor j in right:if abs(i[0]-j[0])<=d and abs(i[1]-j[1])<=d: #如果右侧部分点在i点的(d,2d)之间if get_distance((i,j))<=d: mid_min.append([i,j]) #ij两点的间距若⼩于d则加⼊队列if mid_min:dic=[]for i in mid_min:dic.append({get_distance(i):i})dic.sort(key=lambda x: x.keys())return (dic[0].values())[0]elif dis_l>dis_2:return rminelse:return lmin# 求点对的距离def get_distance(min):return sqrt((min[0][0]-min[1][0])**2 + (min[0][1]-min[1][1])**2)def divide_conquer(s):s.sort(cmp = lambda x,y : cmp(x[0], y[0])) nearest_dots = nearest_dot(s)print nearest_dots测试⼀下,⽐如说要找这些点中最近的⼀对s=[(0,1),(3,2),(4,3),(5,1),(1,2),(2,1),(6,2),(7,2),(8,3),(4,5),(9,0),(6,4)]运⾏⼀下divide_conquer(s),最终打印出[(6, 2), (7, 2)],Bingo。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
分治法所能解决的问题具有以下几个特征: 分治法所能解决的问题具有以下几个特征:
1.该问题的规模缩小到一定的程度就可以容易地解决; 1.该问题的规模缩小到一定的程度就可以容易地解决; 该问题的规模缩小到一定的程度就可以容易地解决 2.该问题可以分解为若干个规模较小且基本相同的子问 2.该问题可以分解为若干个规模较小且基本相同的子问 题。 3.利用该问题分解出的子问题的解可以合并为该问题的 3.利用该问题分解出的子问题的解可以合并为该问题的 解;
分治策略解决问题
问题1 问题1:找出伪币
一个装有1 6枚硬币的袋子 一个装有1 6枚硬币的袋子,1 6枚硬币中有一个 枚硬币的袋子, 6枚硬币中有一个 是伪造的, 是伪造的,并且那个伪造的硬币比真的硬币要轻 一些。你的任务是找出这枚伪造的硬币。 一些。你的任务是找出这枚伪造的硬币。 为了帮助你完成这一任务, 为了帮助你完成这一任务,将提供一台可用来比 较两组硬币重量的仪器,比如天平。 较两组硬币重量的仪器,比如天平。利用这台仪 可以知道两组硬币的重量是否相同。 器,可以知道两组硬币的重量是否相同。
找金块的示例图
方法2 方法2:
n≤2,识别出最重和最轻的金块,一次比较就足够 ≤2,识别出最重和最轻的金块, 了。 n>2,第一步,把这袋金块平分成两个小袋A和B。 第一步,把这袋金块平分成两个小袋A 第二步,分别找出在A 中最重和最轻的金块。 第二步,分别找出在A和B中最重和最轻的金块。设 A中最重和最轻的金块分别为HA 与LA,以此类推, 中最重和最轻的金块分别为HA LA,以此类推, B中最重和最轻的金块分别为HB 和LB。第三步, 中最重和最轻的金块分别为HB LB。第三步, 通过比较HA HB,可以找到所有金块中最重的; 通过比较HA 和HB,可以找到所有金块中最重的; 通过比较LA LB,可以找到所有金块中最轻的。 通过比较LA 和LB,可以找到所有金块中最轻的。 在第二步中, 则递归地应用分而治之方法。 在第二步中,若n>2,则递归地应用分而治之方法。
方法3 方法3
分析
上述三种方法,分别需要比较18次,8次,4次 上述三种方法,分别需要比较18次,8次,4次, 那么形成比较次数差异的根据原因在哪里? 那么形成比较次数差异的根据原因在哪里? 方法1:每枚硬币都至少进行了一次比较 每枚硬币都至少进行了一次比较, 方法1:每枚硬币都至少进行了一次比较,而 有一枚硬币进行了15次比较 有一枚硬币进行了15次比较 方法2:每一枚硬币只进行了一次比较 方法2:每一枚硬币只进行了一次比较 方法3:将硬币分为两组后一次比较可以将硬 方法3:将硬币分为两组后一次比较可以将硬 币的范围缩小到了原来的一半, 币的范围缩小到了原来的一半,这样充分地 利用了只有1枚伪币的基本性质。 利用了只有1枚伪币的基本性质。
可对上述改进少1 可对上述改进少1次
int max=a[1],i,j=1; for(i=2;i<=n;i++){ if(a[i]>max){ max=a[i];j=i;} } for(i=j+1;i<=n;i++){ a[i-1]=a[i];} a[imin=a[1]; for(i=2;i<=nfor(i=2;i<=n-1;i++){ if(a[i]<min){ min=a[i];} }
分析
当已知区间(a,b)内有一个根时 用二分法求根, 当已知区间(a,b)内有一个根时,用二分法求根, 内有一个根时, 若区间(a,b)内有根 则必有f(a)*f(b)&l。重 复执行如下的过程: 复执行如下的过程: (1)若a+0.0001>b或f((a+b)/2)=0, (1)若a+0.0001>b或f((a+b)/2)=0,则可确 定根为(a+b)/2并退出过程 并退出过程; 定根为(a+b)/2并退出过程; (2)若 (2)若f(a)* f((a+b)/2)<0,则由题目给出的定 f((a+b)/2)<0, 理可知根在区间(a,(a+b)/2)中 理可知根在区间(a,(a+b)/2)中,故对区间重复 该过程; 该过程; (3)若 (3)若f(a)* f((a+b)/2)>0 ,则必然有 f((a+b)/2)* f(b)<0 ,根在((a+b)/2,b)中, 根在((a+b)/2,b)中 对此区间重复该过程。 对此区间重复该过程。 执行完毕,就可以得到精确到0.0001的根 的根。 执行完毕,就可以得到精确到0.0001的根。
分治思想
所谓分治,就字面意思而言,就是分而治之, 所谓分治,就字面意思而言,就是分而治之,将一个问题 分解成为若干个与原有问题相似但规模较小的子问题, 分解成为若干个与原有问题相似但规模较小的子问题,然 后递归的求解这些子问题, 后递归的求解这些子问题,最后合并这些子问题的结果就 得到原问题的解了。可以用很简单的话来形容分治: 得到原问题的解了。可以用很简单的话来形容分治:“大 事化小,小事化了” 事化小,小事化了”。 有将问题一分为二,也有将问题一分为三或一分为N等份。 有将问题一分为二,也有将问题一分为三或一分为N等份。 对每一等份分别进行解决后,原问题就可以很快得以解决。 对每一等份分别进行解决后,原问题就可以很快得以解决。 因此一个问题能否用分治法解决,关键是看该问题是否能 因此一个问题能否用分治法解决,关键是看该问题是否能 将原问题分成n个规模较小而结构与原问题相似的子问题。 将原问题分成n个规模较小而结构与原问题相似的子问题。 递归的解决这些子问题, 递归的解决这些子问题,然后合并其结果就得到原问题的 解。 n=2时的分治法又称二分法 时的分治法又称二分法。 当n=2时的分治法又称二分法。
有形如: +cx+d=0这样的一个一元三次 有形如:ax3+bx2+cx+d=0这样的一个一元三次 方程。给出该方程中各项的系数(a, 方程。给出该方程中各项的系数(a,b,c,d均为实 并约定该方程存在三个不同实根(根的范围在数),并约定该方程存在三个不同实根(根的范围在100至100之间 100至100之间),且根与根之差的绝对值>=1。要 之间) 且根与根之差的绝对值>=1。 求由小到大依次在同一行输出这三个实根( 求由小到大依次在同一行输出这三个实根(根与根之 间留有空格) 并精确到小数点后4 间留有空格),并精确到小数点后4位。 提示:记方程f(x)=ax +cx+d,若存在2 提示:记方程f(x)=ax3+bx2+cx+d,若存在2个 )<0,则在(x 数x1和x2,且x1<x2,f(x1)*f(x2)<0,则在(x1, x2)之间一定有一个根。 之间一定有一个根。 样例 输入: 输入:1 -5 -4 20 输出: 输出:-2.00 2.00 5.00
分析
如果精确到小数点后两位,可用简单的枚举法:将x 如果精确到小数点后两位,可用简单的枚举法: 100.00(步长0.01) 逐一枚举, 从-100.00 到100.00(步长0.01) 逐一枚举, 得到20000个 f(x),取其值与0 得到20000个 f(x),取其值与0最接近的三个 f(x),对应的x即为答案。 f(x),对应的x即为答案。而题目已改成精度为小数 点后4 枚举算法时间复杂度将达不到要求。 点后4位,枚举算法时间复杂度将达不到要求。 直接使用求根公式,极为复杂。加上本题的提示给 直接使用求根公式,极为复杂。 我们以启迪:采用二分法逐渐缩小根的范围, 我们以启迪:采用二分法逐渐缩小根的范围,从而 得到根的某精度的数值
基本步骤
一般分为三步递归进行 1.分解:将原问题分解为若干个规模较小,相互独 1.分解 将原问题分解为若干个规模较小, 分解: 与原问题形式相同的子问题; 立,与原问题形式相同的子问题; 2.解决:若子问题规模较小而容易被解决则直接求 2.解决 解决: 否则递归地解各个子问题; 解,否则递归地解各个子问题; 3.合并:将该层递归各个子问题的解合并为原问题 3.合并 合并: 的解。 的解。
分治过程
比较过程
2
2
分析
从图例可以看出,当有8个金块的时候,方法1需要 从图例可以看出,当有8个金块的时候,方法1 比较15-16次 方法2只需要比较10次 比较15-16次,方法2只需要比较10次,那么形成比 较次数差异的根据原因在哪里? 较次数差异的根据原因在哪里? 其根本原因在于方法2对金块实行了分组比较。 其根本原因在于方法2对金块实行了分组比较。 对于N枚金块,我可以推出比较次数的公式: 对于N枚金块,我可以推出比较次数的公式: 假设n 的次幂, 为所需要的比较次数。 假设n是2的次幂,c(n)为所需要的比较次数。 方法1 )=2n方法1: c(n)=2n-1 方法2 c(n 2c(n 2。 方法2:c(n) = 2c(n/2 ) + 2。 使用迭代方法可知c(n 3n 由c(2)=1, 使用迭代方法可知c(n) = 3n/2 - 2。 在本例中,使用方法2比方法1少用了2 5% 在本例中,使用方法2比方法1少用了2 5%的比较次 数。
问题2 问题2:金块问题
有一个老板有一袋金块。 有一个老板有一袋金块。每个月将有两名雇员会因 其优异的表现分别被奖励一个金块。按规矩, 其优异的表现分别被奖励一个金块。按规矩,排名 第一的雇员将得到袋中最重的金块, 第一的雇员将得到袋中最重的金块,排名第二的雇 员将得到袋中最轻的金块。根据这种方式, 员将得到袋中最轻的金块。根据这种方式,除非有 新的金块加入袋中, 新的金块加入袋中,否则第一名雇员所得到的金块 总是比第二名雇员所得到的金块重。 总是比第二名雇员所得到的金块重。如果有新的金 块周期性的加入袋中, 块周期性的加入袋中,则每个月都必须找出最轻和 最重的金块。假设有一台比较重量的仪器, 最重的金块。假设有一台比较重量的仪器,我们希 望用最少的比较次数找出最轻和最重的金块。 望用最少的比较次数找出最轻和最重的金块。