简明易懂的算法文章-浅析分治算法

(翻译文)
    本文介绍分治算法的工作原理,同时,将分治算法与其他解决递归问题的方法进行比较。
    分治算法是一种解决大问题的策略,解决思路如下:
    1.将问题分解为较小的子问题;
    2.解决子问题,然后
    3.合并它们以获得所需的输出。
    要使用分治法,需要使用递归。

1. 分治算法如何工作?

    涉及的步骤如下:
    1.分解:使用递归将给定问题分为子问题;
    2.处理:递归求解较小的子问题。如果子问题足够小,则直接求解。
    3.组合:合并子问题的解决方案,这是递归过程的一部分,得到实际问题的解。
    让我们借助示例来理解这个概念。
    在这里,我们将使用分治的方法对数组进行排序(即合并排序,merge sort)。
    1.待排序的数组如下:
在这里插入图片描述
    2.将数组分为两部分。
在这里插入图片描述
    同样,将每个部分递归地分为两半,直到获得单个元素。
在这里插入图片描述
    3.现在,以排序的方式组合各个元素。在这里,划分和合并的步骤并存。
在这里插入图片描述

2. 计算复杂度

    分治法的复杂度是用主定理计算的。

T(n) = aT(n/b) + f(n),
在这里,
n = 输入大小
a = 递归中子问题的数量
n/b = 每个子问题的大小。假定所有子问题都具有相同的大小。
f(n) = 在递归调用之外完成的工作的成本,包括划分问题的成本和合并解决方案的成本

    让我们举一个例子来了解递归问题的时间复杂度。
    对于合并排序,等式可以写成:

T(n) = aT(n/b) + f(n)
     = 2T(n/2) + O(n)
这里,
a = 2 (每次将一个问题分为2个子问题)
n/b = n/2 (每个子问题的大小是输入的一半)
f(n) = 划分问题和合并子问题所用的时间
T(n/2) = O(n log n) (要理解这一点,请参考主定理。)

现在, T(n) = 2T(n log n) + O(n)
          ≈ O(n log n)
3. 分治vs动态方法

    分而治之的方法将问题分为较小的子问题,这些子问题可以递归进一步解决。每个子问题的结果都不存储,而在动态方法中,每个子问题的结果均存储,以供将来参考。
    当多次尝试解决同一个子问题无效时,使用分而治之的方法。当未来要多次使用子问题的结果时,请使用动态方法。
    让我们通过一个例子来理解这一点。假设我们试图列出斐波那契数列。然后:
    分而治之的方法:

fib(n)
    If n < 2, return 1
    Else , return f(n - 1) + f(n -2)

    动态方法:

mem = [ ]
fib(n)
    If n in mem: return mem[n] 
    else,     
        If n < 2, f = 1
        else , f = f(n - 1) + f(n -2)
        mem[n] = f
        return f

    使用动态方法时,mem 存储每个子问题的结果。

4. 分治算法的优势
  • 用朴素方法计算两个矩阵相乘的复杂度为 O(n3),而使用分治法是 O(n2.8074)。这种方法还简化了诸如汉诺塔之类的其他问题。
  • 这种方法适用于多处理系统。
  • 它有效地利用了内存缓存。
5. 分治的应用
  • 二元搜索
  • 合并排序
  • 快速排序
  • 斯特拉森矩阵乘法
  • 唐津算法
参考文献

https://www.programiz.com/dsa/divide-and-conquer

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值