分治算法

之前我们介绍过了MapReduce框架,而MapReduce框架的本质就是分治算法,
附上链接MapReduce如何让数据完成一次旅行

如何理解分治算法

分治算法的核心就是,分而治之,也就是将原问题划分成为n个规模比较小,并且和原问题相似的子问题,递归的解决这些子问题,然后再合并结果,得到原问题的解。

当然,分治算法和昨天说的贪心算法的本质也是差不多的,都是一种处理问题的思想,而不是编程的框架。从实际上来说,分治算法一般都适合用递归来实现。

在分治算法的递归实现中,每一层递归都包含了这样三个操作:

  1. 分解:将原问题分解成一系列子问题。
  2. 解决:递归地求解各个子问题,若子问题足够小,则直接求解。
  3. 合并:将子问题的结果合并成原问题。

分治算法的原则如下:

  1. 原问题和子问题使用相同的计算模式
  2. 子问题之间相互独立,不会相互影响
  3. 当子问题足够小,可以直接求解得出答案
  4. 子问题解决后,还可以合并为原问题期望的结果,而且合并的时间复杂度要低于原问题直接解决的时间复杂度

分治算法应用举例

在这里,我们先引入一下有序度和逆序度的概念:

有序度:有序度是数组中具有有序关系的元素对的个数。有序元素对用数学表达式表示就是这样:

有序元素对a[i]<=a[j],如果i<j

在这里插入图片描述

而当我们拥有一个单调递增序列的时候,那么有序度就是最大化的,为n*(n-1)/2,这种情况可以达到满有序度

逆序度:概念和有序度相反。

然后我用冒泡排序举个例子:

在这里插入图片描述

然后回到我们原来的话题。

  • 假设我们有n个int类型的数据,如何用代码求出一组数据的有序对个数或者逆序对个数呢?

首先先说一下我们都知道的解决方法:来个n²复杂度,满足条件就存入map,不满足就不存。最后print一波就ok了。那么还有没有更加高效的方法呢?

那就是分治算法了,思路如下:

  1. 将这些数放入数组,将数组拆成前后两半A1 A2
  2. 计算A1和A2的逆序对个数K1和K2
  3. 计算A1与A2之间的逆序对个数K3
  4. 最终答案就是K1+K2+K3

但分治算法原则上要求合并的代价不能太大,那么如何计算出子问题A1与A2之间的逆序对个数呢?

这就要用到归并排序了,因为归并排序的本质就是将原本有序的小数组合并为大数组,每次调换位置我们就用一个局部变量进行统计,然后就能求出k3了。

在这里插入图片描述

这个问题的难点就在于归并排序上了,因为不是很多人都能想到,所以,我们的方法不能局限于此,也要去思考类似于归并排序的排序,可以自己制作一个算法。

而关于分治算法还有很多典型案例,建议多刷题。

分治算法在海量数据中的应用

当我们给10GB的文件按照某种字段排序,首先想到了就是性能问题,而且硬件本身也有一定会受到局限,所以就无法单纯的靠简单的排序算法来解决了。

要解决这种数据量大到硬件无法支撑的情况时,就要采用分治的思想。将大数据拆成小数据,然后单独加载到内存中计算,最后再合并起来去排序。

但我们也可以开阔一下思路,比如说用sql分桶方式去排序,划分区间去排序。

又或者,我们可以把数据存放在GFS等这种大数据系统上,分布式计算,加快效率。

那么为什么MapReduce就是分治思想

首先,当我们的数据大到了上百T的情况下,一台机器无论如何也无法提升效率了,所以使用集群就是大势所趋。但是MapReduce终究是一个框架,用Yarn去配合资源调度,同时自己也用JobTracker当做监控器,再通过Zookeeper做风险处理,在一台机器宕机的时候还能快速切换机器。

但更希望将MapReduce理解成一种思维,也就是分而治之的思维。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值