码迷,mamicode.com
首页 > 其他好文 > 详细

分治法

时间:2015-03-06 20:30:42      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:

个人理解

简单的说, 分治法就是把一个相对大的问题分成类似的小问题, 求得这些小问题的解(相对简单)再进行适当的合并, 最终就解决了一个相对复杂的问题。

这其中蕴含的思想我自己总结的如下:

  1. 不是正面来解决一个相对复杂的问题, 而是将这个问题进行分解成为相对来说简单并且不是那么复杂的问题, 这是一种化繁为简的思路, 处理上更加灵活。
  2. 其中蕴含着类比的思想, 也可以说是递归的思想, 大问题与小问题的解法是类似的, 从而可以递归的解决问题。

一般步骤

采用分治法的一般步骤概括如下:

  1. 递归
  2. 合并

分即使把大问题分解成为小问题, 常见的做法是一分为二, 比如, 排序可以将整个数组一分为二再进行排序。

递归即是可以将问题一直分解下去, 直到某个临界的条件满足了, 再递归的返回去。

第三部是合并, 只有将小问题的解进行合并做相应的处理, 才能得到最终的答案, 个人感觉这步是最难的, 如何设计巧妙的合并方法也是很重要的, 并且在编程上也有一定的难度。在平时的练习过程中一定要细细体会。

算法举例

这里先举两个简单的分治法的例子, 将上面所讲的理论的东西在具体的实例中融汇融汇。

1. 二分法搜索

首先上代码(Python)

技术分享
def BinSearch(data, low, high, goal):
      out = None
      if low > high:
            return out
      
      mid = (low + high) / 2
      if goal < data[mid]:
            out = BinSearch(data, low, mid - 1, goal)
      elif goal > data[mid]:
            out = BinSearch(data, mid + 1, high, goal)
      else:
            out = mid
            
      return out
View Code

 

问题是要解决在一个数组中搜索要求的目标,如果按照一般的思路,一个个查找的话,算法复杂度为$O(n)$。这里考虑到,在一个较大的数组中查找一个数与在一个较小的数组中查找一个数其实是一样的,那么自然的就可以使用二分法来解决这个问题,最后合并的过程也很简单找到了就返回下标,没有的话返回None,常数次操作。上面代码给出的是递归的形式。下面分析一下算法复杂度,很显然$T(n) = T(n / 2) + O(1)$,那么根据主公式很容易计算出算法复杂度为$O(n) = O(log(n))$。这里就看出分治法的优势来了。

2. 归并排序

还是先上代码

技术分享
def MergeSort(data, low, high):
      if low == high:
            return
      
      #divide
      mid = (low + high) / 2
      MergeSort(data, low, mid)
      MergeSort(data, mid + 1, high)

      #merge
      data_copy = data[low : high + 1]
      i = low
      k = 0
      m = mid + 1 - low
      left = data_copy[k]
      right = data_copy[m]
      
      while(True):
            if left <= right:
                  data[i] = left
                  k += 1
                  if k < (mid - low + 1):
                        left = data_copy[k]
                  else:
                        data[i + 1: high + 1] = data_copy[m :]
                        return 
            else:
                  data[i] = right
                  m += 1
                  if m < (high - low + 1):
                        right = data_copy[m]
                  else:
                        data[i + 1: high + 1] = data_copy[k : mid + 1 - low]
                        return 
            i += 1
View Code

 

同样的对一组比较多的数据进行排序与对一组较少的数据进行排序实质上是一样的,所以也可以使用分治法,这里所介绍的是归并排序算法。首先是分的过程,比较简单,接下来归并的过程稍微复杂一些,它要求将两个排列好的序列再次按照大小规则排列在一起,这相对排序来说已经简化了很多,显然复杂度为$O(n)$。这里我给出的方法的代码量比较多,当然也有比较简单的写法。所以从整体来分析复杂度的话,即$T(n) = 2T(n / 2) + O(n)$,再次根据主方法可以很容易的算出$O(nlogn)$的复杂度。相对原来$O(n)$而言,是优化了一些。但是此算法也带了$O(n)$的空间开销。

算法编程题

这里是leetcode上关于分治法的编程练习题,可以多练习。

实际中的应用

这里想多举一些分治法在实际情况中的具体应用。由于目前暂时还没有看到比较好的例子,待以后慢慢的积累以及更新!!

分治法

标签:

原文地址:http://www.cnblogs.com/Gru--/p/4318977.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!