数据结构与算法,系列文章传送地址,请点击本链接。

目录

一、如何理解分治算法

二、分治算法需要满足的条件

三、分治算法--代码模板

四、案例

五、分治思想在海量数据处理中的应用


一、如何理解分治算法

分治算法(divide and conquer)的核心思想其实就是四个字,分而治之 ,也就是将原问题划分成 n 个规模较小,并且结构与原问题相似的子问题,递归地解决这些子问题,然后再合并其结果,就得到原问题的解。

这个定义看起来有点类似递归的定义。关于分治和递归的区别,分治算法是一种处理问题的思想,递归是一种编程技巧。实际上,分治算法一般都比较适合用递归来实现。分治算法的递归实现中,每一层递归都会涉及这样三个操作:

分解:将原问题分解成一系列子问题;

解决:递归地求解各个子问题,若子问题足够小,则直接求解;

合并:将子问题的结果合并成原问题。

二、分治算法需要满足的条件

分治算法能解决的问题,一般需要满足下面这几个条件:

  1. 原问题与分解成的小问题具有相同的模式;
  2. 原问题分解成的子问题可以独立求解,子问题之间没有相关性,这一点是分治算法跟动态规划的明显区别,等我们讲到动态规划的时候,会详细对比这两种算法;
  3. 具有分解终止条件,也就是说,当问题足够小时,可以直接求解;
  4. 可以将子问题合并成原问题,而这个合并操作的复杂度不能太高,否则就起不到减小算法总体复杂度的效果了。

三、分治算法--代码模板

Java
public void divide_conquer(problem,param1,param2,...) {
    //1、终点结束目标
    if (problem == null) {
        return result;
    }

//2、数据预处理
    data = prepare_data(problem);
    subproblems = split_problem(problem,data);

//3、处理子问题
    subresult1 = self.divide_conquer(subproblems[0],param1,...);
    subresult2 = self.divide_conquer(subproblems[1],param1,...);
    subresult3 = self.divide_conquer(subproblems[2],param1,...);
    ...
    //4、合并子问题
    result = process_result(subresult1,subresult2,subresult3,...);

//5、还原当前状态

}

四、案例

假设我们有 n 个数据,统计逆序读的个数。比如,2,4,3,1,5,6的逆序对个数为4.

解题思路:

最笨的方法是,拿每个数字跟它后面的数字比较,看有几个比它小的。我们把比它小的数字个数记作 k,通过这样的方式,把每个数字都考察一遍之后,然后对每个数字对应的 k 值求和,最后得到的总和就是逆序对个数。不过,这样操作的时间复杂度是 O(n^2)。那有没有更加高效的处理方法呢?

我们用分治算法来试试。我们套用分治的思想来求数组 A 的逆序对个数。我们可以将数组分成前后两半 A1 和 A2,分别计算 A1 和 A2 的逆序对个数 K1 和 K2,然后再计算 A1 与 A2 之间的逆序对个数 K3。那数组 A 的逆序对个数就等于 K1+K2+K3。

private int num = 0; // 全局变量或者成员变量

public int count(int[] a, int n) {

num = 0;

mergeSortCounting(a, 0, n-1);

return num;

}

private void mergeSortCounting(int[] a, int p, int r) {

if (p >= r) return;

int q = (p+r)/2;

mergeSortCounting(a, p, q);

mergeSortCounting(a, q+1, r);

merge(a, p, q, r);

}

private void merge(int[] a, int p, int q, int r) {

int i = p, j = q+1, k = 0;

int[] tmp = new int[r-p+1];

while (i<=q && j<=r) {

if (a[i] <= a[j]) {

tmp[k++] = a[i++];

} else {

num += (q-i+1); // 统计p-q之间,比a[j]大的元素个数

tmp[k++] = a[j++];

}

}

while (i <= q) { // 处理剩下的

tmp[k++] = a[i++];

}

while (j <= r) { // 处理剩下的

tmp[k++] = a[j++];

}

for (i = 0; i <= r-p; ++i) { // 从tmp拷贝回a

a[p+i] = tmp[i];

}

}

五、分治思想在海量数据处理中的应用

分治算法思想的应用是非常广泛的,并不仅限于指导编程和算法设计。它还经常用在海量数据处理的场景中。我们前面讲的数据结构和算法,大部分都是基于内存存储和单机处理。但是,如果要处理的数据量非常大,没法一次性放到内存中,这个时候,这些数据结构和算法就无法工作了。

比如,给 10GB 的订单文件按照金额排序这样一个需求,看似是一个简单的排序问题,但是因为数据量大,有 10GB,而我们的机器的内存可能只有 2、3GB 这样子,无法一次性加载到内存,也就无法通过单纯地使用快排、归并等基础算法来解决了。

要解决这种数据量大到内存装不下的问题,我们就可以利用分治的思想。我们可以将海量的数据集合根据某种方法,划分为几个小的数据集合,每个小的数据集合单独加载到内存来解决,然后再将小数据集合合并成大数据集合。实际上,利用这种分治的处理思路,不仅仅能克服内存的限制,还能利用多线程或者多机处理,加快处理的速度。

比如刚刚举的那个例子,给 10GB 的订单排序,我们就可以先扫描一遍订单,根据订单的金额,将 10GB 的文件划分为几个金额区间。比如订单金额为 1 到 100 元的放到一个小文件,101 到 200 之间的放到另一个文件,以此类推。这样每个小文件都可以单独加载到内存排序,最后将这些有序的小文件合并,就是最终有序的 10GB 订单数据了。

如果订单数据存储在类似 GFS 这样的分布式系统上,当 10GB 的订单被划分成多个小文件的时候,每个文件可以并行加载到多台机器上处理,最后再将结果合并在一起,这样并行处理的速度也加快了很多。不过,这里有一个点要注意,就是数据的存储与计算所在的机器是同一个或者在网络中靠的很近(比如一个局域网内,数据存取速度很快),否则就会因为数据访问的速度,导致整个处理过程不但不会变快,反而有可能变慢。

声明:文章内容是极客时间专栏学习的学习笔记,会做简化或调整,欢迎大家留言和评论。

数据结构与算法,系列文章传送地址,请点击本链接。https://blog.csdn.net/wanghaiping1993/article/details/125092448

数据结构与算法_03_分而治之的分治算法相关推荐

  1. 哈工大(威海)算法实验一:分治算法实验大作业

    哈工大(威海)算法实验一:分治算法实验大作业 题目 某一高等院校有汽车学院.材料学院.计算机学院.软件学院:每个学院的一年级第一学期都开英语.高数.线代课程.每个学院每学期的成绩已经分别登录在同一个E ...

  2. java分治_【Java算法】什么是分治算法?

    1.什么是分治算法? 分治法(Divide-and-Conquer)是一种很重要的算法. 分治就是"分而治之"的意思,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子 ...

  3. python分治算法_黄哥Python:分治算法(Divide-and-Conquer)

    分治算法(Divide-and-Conquer) 在计算机科学中,分而治之(简称分治法)是基于多分支递归的算法设计范例.分而治之算法的工作原理是将问题递归分解为两个或多个相同或相关类型的子问题,直到这 ...

  4. NOIP训练营集训笔记—信息学基础算法(倍增与分治算法

      本文摘自清北OI学堂内部笔记,作者潘恺璠,来自柳铁一中曾参加过清北训练营提高组精英班,主要记录的是信息学基础算法.笔记非常详细,特分享给大家! NOIP2019年夏令营正在报名中,6大校区10种班 ...

  5. 常用算法总结(穷举法、贪心算法、递归与分治算法、回溯算法、数值概率算法)

    博主联系方式: QQ:1540984562 微信:wxid_nz49532kbh9u22 QQ交流群:892023501 目录 1.穷举法 2.贪心算法 3.递归与分治算法 4.回溯算法 5.数值概率 ...

  6. 卷王李富贵算法每日一题--分治算法(三)--逃亡

    逃亡 如图1.2所示,设两人分别为甲.乙,则最优方案应该是甲先乘车到达C后下车步行,小车回头接已经走到E的乙,假设在 D相遇,乙乘车到达B时正好甲也步行到达,这样花费的时间最短. 分治算法 v1 是人 ...

  7. 算法每日一题--分治算法(二)-李富贵要上岸985

    题目:魔法石的诱惑 分析一 想要做出这个题,首先得知道:给定一个正整数n,怎么快速计算出n的阶乘尾部0的个数 这种题嘛,主要是找规律,找出规律来后就很简单了.ok,先想想,阶乘最后有0,如果一个偶数和 ...

  8. 算法每日一题--分治算法(一)-李富贵要上岸985

    文章目录 前言 注 分治算法(一) 例题一:二分查找(折半查找) 递归法 踩坑 非递归 前言 之前主要是学人工智能相关的知识,从Python基础到数据分析到人工智能等等,那些知识一般是用到了,学习的过 ...

  9. java 整数乘法的算法,大整数乘法——分治算法的时间复杂度

    1.1原始的低效算法 我们将n位(为方便讨论简化问题,我们假设n是2的幂)十进制整数(二进制也可以)X.Y都分为2段,每段的长度是n/2位. 如果现在直接用递归或分治进行编程,其算法复杂度为: 其中: ...

最新文章

  1. ubuntu 禁用透明大页_Linux关于透明大页的使用与禁用介绍
  2. SQL UNION 操作符
  3. 杭电1016Java实现
  4. etcher制作mac启动盘_如何快速制作 macOS Mojave U盘启动盘,并重装Mac系统
  5. SpringMVC-方法四种类型返回值总结,你用过几种?
  6. LeetCode 1221. 分割平衡字符串
  7. TchApp 为dotnet core配个UI,项目已托管github
  8. FormView用法
  9. SSD物体检测(附源代码,可以直接运行)
  10. sharepoint安装心得-.net与sharepoint安装 sharepoint安装心得_过程(一)
  11. FGUI手势案例代码
  12. 《算法导论》+第四版++答案
  13. 腾讯与清华大学物理系签署合作备忘录,探索材料计算新领域
  14. 百度开发者中心如何创建mysql数据库_百度开发者中心BAE新建Java应用
  15. turicreate 视频_iOS 推出的turiCreate功能(一) 图片识别
  16. 回收站清空几天可找回?回收站清空的文件怎么恢复?2个方案
  17. 组件、插件、控件的区别
  18. 用chrome浏览器将pdf paper整篇翻译成中文
  19. 排列组合的简单应用(隔板法)
  20. mysql中更改数据库名字_【实操篇】_MySQL如何更改数据库名字?

热门文章

  1. 明明觉醒为啥服务器还在维护,文明觉醒无法连接服务器是什么原因
  2. ubuntu下的Redis操作命令
  3. 中国式家长计算机入门怎么去的,中国式家长新手入门怎么玩_新手入门注意事项...
  4. Set集合概述和特点
  5. js弹框,并指定的url
  6. 2017 JavaOne参会感想
  7. python mpi4py 读取json_Python:使用mpi4py通过spawn将数组bcast到其他脚本
  8. 实验室三维磁场电磁铁的主要用途及技术指标
  9. 使用和调整电磁铁时应注意的事项
  10. 定时关闭电脑——《超级处理器》应用