27.分治算法

分治算法

分治算法的核心思想就是将一个规模N的问题拆分为K个规模小的子问题,这些子问题相对嘟咧且与原问题相同或类似,求出所有子问题的解,然后再合并所有子问题的结果即是原问题的解。

步骤

  1. 分解: 将原问题拆分若干的规模较小,容易解决,相对独立性质与原问题相同子问题
  2. 求解: 直接当子问题递归分解到较小,容易解决的问题,然后得出结果
  3. 合并:将各个子问题的结果通过某种方法合并得到原问题的解

它的一般的算法设计模式如下:

Divide-and-Conquer§

if |P|≤n0

then return(ADHOC§)

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

for i←1 to k

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

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

return(T)

其中|P|表示问题P的规模,n0为一阈值,表示当问题P的规模不超过n0时,问题已容易直接解出,不必再继续分解。ADHOC§是该分治法中的基本子算法,用于直接解小规模的问题P,因此,当P的规模不超过n0时直接用算法ADHOC§求解。算法MERGE(y1,y2,…,yk)是该分治法中的合并子算法,用于将P的子问题P1 ,P2 ,…,Pk的相应的解y1,y2,…,yk合并为P的解。

经典的应用场景

  • 快速排序 核心思想将序列一份为2,找到中位数的只,将比中位数值小的放在中位数左边反之右边,一直递归求解到无法再拆分为止
  • 归并排序 核心思想将序列一直拆分到2个元素,无法再拆分,然后将最小单位排序完毕之后,再将上层拆分出来的数列再次排序直到合并完毕
  • 汉诺塔问题 拆分出来最简单的两种情况 任意多的盘看成最底下的一个盘和除去最底下之外的所有盘,步骤为将上面的所有盘移动到B柱,将最底下的盘移动到C柱,然后把剩下的所有盘从B移动到C柱即可、

汉诺塔问题的分支算法实现

public class HanoiTower {

    public static void main(String[] args) {
        hanoitower(5, 'A', 'B', 'C');
    }

    /**
     * @param num 盘的数量
     * @param a   起点柱
     * @param b   中间过渡柱
     * @param c   终点柱
     */
    public static void hanoitower(int num, char a, char b, char c) {
        if (num == 1) {
            System.out.println("第1个盘子从 " + a + " -> " + c);
        }
        if (num > 1) {
            // 将盘一分为二看 先把上面的左右盘移动到 B 柱子 此时可以将B柱子看成终点 A柱是起点 B柱是终点 C柱是在中间过滤
            hanoitower(num - 1, a, c, b);
            // 将最后一个盘 从 a 移动到 c
            System.out.println("第" + num + "个盘子从 " + a + " -> " + c);
            // 将 剩下的盘从B 移动到 C 相当于现在B是起点 C是重点
            hanoitower(num - 1, b, a, c);
        }
    }
}

你可能感兴趣的:(数据结构)