算法设计之分治法策略

Posted 聊寂园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法设计之分治法策略相关的知识,希望对你有一定的参考价值。

前言: 分治法  :divide and conquer 又称分而治之,是一种非常有用的算法设计策略,它是将一个难以解决的大问题规模划分为一些规模较小的子问题,分别求解每个子问题的解,然后合并子问题的解。理所当然,设计分治法需要分三个步骤:

(1)divide 划分,把问题规模划分为k个规模较小的子问题,(一般k=2)

(2)conquer 治,即递归(recursive)地解决子问题

(3)combine 合并子问题的解

  关于步骤(1)划分问题规模一般k=2是基于平衡子问题的启发式思想,它几乎总是比子问题规模不等的做法好。

在第二步解决子问题我们谈到递归,这也是一个依据,一个问题规模划分到什么程度才能非常方便的求解?这就是递归设计思想中的平凡问题和子问题。当一个问题规模不断划分直到成为一个平凡问题时(也就是递归基),我们可以在O(1)时间内完成该问题的求解。举个例子

1 int sum(int a[],int n)
2 {
3 return  (n<1)?0:sum(a,n-1)+a[n-1];
4 }

没错就是一个简单的数组求和,却蕴含着递归思想,以及分治算法思想

从上面的代码分析和案例分析中,我们看到了分治法的魅力所在,其实在数据结构中,关于内部排序最常用的两个算法 归并排序和快速排序,都是采用了分治法思想设计的,下一篇博文我来讲解一下对此两种算法的认识,在结束之前,我们先热身一下,分析二分查找算法

 binary search 二分查找,是在已递增排序好的数组中找给定的x元素是否存在,它也用到了分治思想,我按照分治法设计三步骤给大家剖析一下

(1)divide  分,就是把给定的x和数组中间那个元素比较

(2)conquer  如果x<middle,则只在左子数组中递归查找;否则,只在右子数组中递归查找即recursivly only in  one subarray

(3) combine 可是说是没有合并子问题解这一步骤,因为只需要比较找到即可返回布尔值就行

首先我们都知道递归是需要设计平凡问题的,否则无法确定如何停止递归,就本问题而言,每次都是在subarray中查找,如果subarray长度<=0,即不存在子数组时,表示递归基

具体算法实现如下:

 1 bool binarySearch(int a[],int x,int low,int high)
 2 {
 3 if(low>high)
 4    return false;
 5 int mid=(low+high)>>1;
 6 if( a[mid]==x)
 7   return true;
 8 else if(a[mid]<x)
 9   binarySearch(a,x,mid+1,high);
10 else 
11   binarySearch(a,x,low,mid-1);
12 }

分析该算法时间复杂度

T(n)=1 * O(n/2)+O(1);

这是因为每次递归解决子问题比较之后都只会在一个子区间进行查找,且每次比较都是常数性的。

下一篇会分析二分查找与一般分治算法时间复杂度的不同。

二分算法思想在实际生活中也有应用,比如求解一些只在一个子区间递归解决问题的复杂问题。

以上是关于算法设计之分治法策略的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法之深入解析常用的七大算法设计策略

算法复习_分治算法之二分搜索棋盘覆盖快速排序

算法:用分治法设计gray码

算法设计与分析分治法

基础算法 分治法之合并排序

计算机算法设计与分析之递归与分治策略——二分搜索技术