分治算法例子集锦

描述:

两部分组成

分(divide):递归解决较小的问题

治(conquer):然后从子问题的解构建原问题的解

三个步骤

1、分解(Divide):将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;

2、解决(Conquer):若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;

3、合并(Combine):将各个子问题的解合并为原问题的解。

四个适用条件

1、该问题的规模缩小到一定的程度就可以容易地解决;

2、该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。

3、利用该问题分解出的子问题的解可以合并为该问题的解;

4、该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。

(上述的第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;第二条特征是应用分治法的前提,它也是大多数问题可以满足的,此特征反映了递归思想的应用;第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑贪心法或动态规划法。第四条特征涉及到分治法的效率,如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。)

伪代码表示

Divide-and-Conquer(P)

1. if |P|≤n0

2. then return(ADHOC(P))

3. 将P分解为较小的子问题 P1 ,P2 ,…,Pk

4. for i←1 to k

5. do yi ← Divide-and-Conquer(Pi) △ 递归解决Pi

6. T ← MERGE(y1,y2,…,yk) △ 合并子问题

7. return(T)

典型实例

求x的n次幂

复杂度为 O(lgn) 的分治算法

#include "stdio.h"
#include "stdlib.h"

int power(int x, int n)
{
    int result;
    if(n == 1)
        return x;
    if( n % 2 == 0)
        result = power(x, n/2) * power(x, n / 2);
    else
        result = power(x, (n+1) / 2) * power(x, (n-1) / 2);

    return result;
}

int main()
{
    int x = 5;
    int n = 3;

    printf("power(%d,%d) = %d \n",x, n, power(x, n));
}

归并排序

http://blog.csdn.net/zwhlxl/article/details/44086683

最大子序列问题

http://blog.csdn.net/zwhlxl/article/details/42649979

参考文章

1、http://raytaylorlin.com/Tech/algorithm/divide-and-conquer/

2、http://hahack.com/wiki/algorithms-divide-and-conquer.html

3、http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741370.html

时间: 2024-11-09 03:53:51

分治算法例子集锦的相关文章

排序算法大集锦_二路归并排序_2&3(分治思想)

第一段代码和合并排序差不多,用它来和第二段代码--二路归并排序作对比. 这一系列博客的特点就是--给出每趟排序的结果 本来想着好好写一下过程,弄个图片什么的,不过觉得网上的解析太多了,都比较好,所以这些博客就算是对自己的总结吧. #include <stdio.h> #include <limits.h> #include <malloc.h> void merge(int *m, int x, int y, int z) { int b1,b2,i,j,k; b1=y

再回首--分治算法

谈起分治算法,首先从字面意思理解:就是将一个问题划分成多个较小的问题的算法.其实正应题目的意思.其基本设计思想就是:将一个难以直接解决的大问题分解成一些规模较小的相同问题以便各个击破,分而治之. 设计步骤:1)分解:分解成若干子问题 2)求解:求解个子问题 3)合并:将子解合并成原问题的解. 在自考的时候,我们遇到的二路归并算法就属于一种分治法.当然,要学会算法,就要找到其核心,抓住其核心了,我们也就明白算法是怎么回事了.下面我们通过二路归并算法找到其核心. 例子:给出一列数:4,2,8,3.利

《数据结构与算法分析 C语言描述》读书笔记——分治算法

书中用求解最大子序列和的方式介绍了分治算法(divide-and-conquer) 分治算法是一种相对快速的算法 运行时间为O(logN) 最大子序列和的问题如下: 给出一组整数 A1  A2 … AN 求∑jk=i Ak 若所有整数均为负 则最大子序列和为0 e.g. 输入-2, 11,-4, 13, -5, -2 输出20(A2到A4) 分治算法就如同字面描述的一样 先分再治 分 指的是将问题分为两部分几乎相同的子问题 进行递归求解 治 指的是将 分 的解通过简单的手段合并 得到最终解 对于

【数据结构】分治算法求解假硬币问题

问题描述: 概念 分治算法的基本思想是将一个大的复杂的问题分解成多个小的.容易解决的问题,通过解决这些小问题进而解决这个大问题. 使用分治算法需要待求解问题能够简化为若干个小规模的相同的问题,通过逐步划分,达到一个易于求解的阶段,而直接进行求解,在程序中可以使用递归方法来进行求解. 哈哈,说起来很抽象,举个例子就好理解了. 一个袋子里有n个硬币,其中一枚是假币,并且假币和真币一模一样,仅凭肉眼无法区分,仅知道假币比真币轻一些,请问如何查找到假币? 分治算法: 我们可以这样做: 将这n个硬币分成两

分治算法(思想)在数据结构中的应用

分治算法: 简单的概括就是将暂时不能解决的大问题分成许多入门的子问题, 如果子问题还是不能解决的话则继续分成子问题,直到子问题小到 可以解决为止的规模,原问题即是子问题的合并. PartOne: 用分治法打印数组a[L,......,R]. 分析: 一个循环就可以了,但是分治算法来解决该怎么做呢? 如果待打印的序列长度为 1,则可以直接打印; 如果待打印的序列长度为 N,则可将其划分为两部分; 第一部分是 1, 后N - 1 是另一个划分,以此类推,直到数组长度是 1. void print(i

【万字博文】分析与设计:插入排序和分治算法、递归和迭代的探讨

插入排序及其解决思路 算法的作用自然不用多说,无论是在校学生,还是已经工作多年,只要想在计算机这条道路走得更远,算法都是必不可少的. 就像编程语言中的"Hello World!"程序一般,学习算法一开始学的便是排序算法.排序问题在日常生活中也是很常见的,说得专业点: 输入是:n个数的一个序列<a1,a2,...,an?1,an> 输出是:这n个数的一个全新的序列<a,1,a,2,...,a,n?1,a,n>,其特征是a,1≤a,2≤...≤a,n?1≤a,n 举

lanczos算法及C++实现(三)实对称三对角阵特征值分解的分治算法

本文属作者原创,转载请注明出处 http://www.cnblogs.com/qxred/p/dcalgorithm.html 本系列目录: lanczos算法及C++实现(一)框架及简单实现 lanczos算法及C++实现(二)实对称阵奇异值分解的QR算法 lanczos算法及C++实现(三)实对称三对角阵特征值分解的分治算法 0. 参考文献 https://en.wikipedia.org/wiki/Divide-and-conquer_eigenvalue_algorithm A. Mel

算法系列之常用算法之一----分治算法

一.基本概念 在计算机科学中,分治法是一种很重要的算法.分治算法,字面上的解释是"分而治之",分治算法主要是三点: 1.将一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题----"分" 2.将最后子问题可以简单的直接求解----"治" 3.将所有子问题的解合并起来就是原问题打得解----"合" 这三点是分治算法的主要特点,只要是符合这三个特点的问题都可以使用分治算法进行解决(注意用词,是"

分治算法学习 Divide and Conquer

分治思想: 分治算法的思想就是 对于某些特定种类的问题  如果问题的规模很小,那么就直接解决,如果问题的规模比较大,那么就把问题先分解为规模小的但是问题相同的子问题 ,并且不断分解直到规模足够小,再递归地解决这些问题 如果原问题可分割成k个子问题,1<k≤n,且这些子问题都可解并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的. 递归与分治经常是一起使用的 能够用分治的情况 : 1.问题复杂性随规模减小而减小 2.问题具有最优子结构性质        最优子结构:如果问题的最优解所包