算法应用之分治法

一、分治法的基本概念

        在生活中当我们遇到复杂的问题时,我们通常会将这个复杂的问题分为几个小的问题或者分为几个步骤来解决,当我们将原问题拆分成若干个小问题或者步骤过后,小问题相对原问题来讲或许会更容易解决,我们通过解决这些小问题,最终达到解决该问题的目的。

        这种解决问题的思想就类似于计算机科学中的“分治法”。分治即“分而治之”,一个规模很大的问题若要直接求解起来是非常困难的,将一个复杂的问题分解为若干个规模较小但是类似于原问题的子问题,子问题可以再分为更小的子问题,最终达到子问题可以简单的直接求解的目的,那么原问题的解即子问题的解的并集。由此将问题简单化处理。

二、分治法的基本思想

       对于一个规模为n的问题,若该问题可以容易的解决(比如说规模n较小)则直接解决;否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归的解决这些小问题,然后再合并这些子问题的解来建立原问题的解。

      2.1、分治法在每层递归时都有三个步骤:

  • 分解(Divide):将问题划分为一些子问题,子问题的形式与原问题一样,只是规模更小
  • 解决(Conquer):递归的解地求解出子问题。如果子问题的规模足够小,则停止递归则直接求解。
  • 合并(Combine):将子问题的解组合成原问题的解

      2.2、分治法的适用条件:

  1. 该问题的规模缩小到一定的程度就可以容易地解决。
  2. 该问题可以分解为若干个规模较小的相同问题。此条件是分治法能够应用的前提,反映了递归思想的应用。
  3. 利用该问题分解出的子问题的解可以合并为该问题的解。此条件是分治法的决定性因素,如果不能满足此条件,那么该问题则不能用分治法解决。
  4. 该问题的解分解出的各个子问题是相互独立的。此条件反映了分治法的解决效率,若是分解后的子问题不是相互的独立的,那么将会有很多不必要的重复的工作出现,导致效率低下。

三、分治法的应用案例

    二分查找

       二分查找是典型的分治法的应用。二分查找的前提是要查找的序列必须是有序的

      二分查找的基本思想:

  1. 在表中间位置选取一个关键字作为记录并将查找序列分为两个集合;
  2. 将表中间记录的关键字与查找关键字相比较,如果两者相等,则查找成功;
  3. 否则比较两者的大小,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表;
  4. 递归进行上面的步骤,直到找到满足条件的记录,使查找成功,或直到字表不存在,此时查找不成功。

     二分查找代码实现(Java)

public static int binarySearch(int[] arr, int a, int b, int x) {

        //a表示要查找序列的开始索引,b表示要查找序列的结束索引,x表示待查找的关键字

        int m = (a + b) / 2;   //将序列一分为二,记录该位置索引

        int n = 0;

        if (a < b) {

            if (x == arr[m]) {    //如果待查的关键字等于所记录索引位置的序列的值

                n = m;    //查找成功,返回该索引

                //否则比较两者的大小,如果中间位置记录的关键字大于查找关键字,
                // 则进一步递归查找前一子表
            } else if (x > arr[m]) {


                n = binarySearch(arr, m + 1, b, x);

                //否则进一步递归查找后一子表
            } else if (x < arr[m]) {
                n = binarySearch(arr, a, m - 1, x);
            }
        } else {

            n = -1;  //查找失败
        }

        return n;
    }

以上便是分治法的一个经典用例;其实有很多问题的求解都用到了分治法,例如:

  1. 求解最大子数组问题
  2. 归并排序
  3. 矩阵乘法的Strassen算法
  4. 快速排序
  5. …………

这里我就不一一介绍了,有兴趣的可以自行下去研究。

四、总结

       分治算法的核心是将一个规模较大的问题分解为几个规模较小的问题,利用递归的思想求解这些子问题,然后将这些子问题的解合并得到原问题的解。分治算法的优点之一在于通过递归的技术往往很容易确定其运行时间

你可能感兴趣的:(算法)