标签:
简单的说, 分治法就是把一个相对大的问题分成类似的小问题, 求得这些小问题的解(相对简单)再进行适当的合并, 最终就解决了一个相对复杂的问题。
这其中蕴含的思想我自己总结的如下:
采用分治法的一般步骤概括如下:
分即使把大问题分解成为小问题, 常见的做法是一分为二, 比如, 排序可以将整个数组一分为二再进行排序。
递归即是可以将问题一直分解下去, 直到某个临界的条件满足了, 再递归的返回去。
第三部是合并, 只有将小问题的解进行合并做相应的处理, 才能得到最终的答案, 个人感觉这步是最难的, 如何设计巧妙的合并方法也是很重要的, 并且在编程上也有一定的难度。在平时的练习过程中一定要细细体会。
这里先举两个简单的分治法的例子, 将上面所讲的理论的东西在具体的实例中融汇融汇。
首先上代码(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
问题是要解决在一个数组中搜索要求的目标,如果按照一般的思路,一个个查找的话,算法复杂度为$O(n)$。这里考虑到,在一个较大的数组中查找一个数与在一个较小的数组中查找一个数其实是一样的,那么自然的就可以使用二分法来解决这个问题,最后合并的过程也很简单找到了就返回下标,没有的话返回None,常数次操作。上面代码给出的是递归的形式。下面分析一下算法复杂度,很显然$T(n) = T(n / 2) + O(1)$,那么根据主公式很容易计算出算法复杂度为$O(n) = O(log(n))$。这里就看出分治法的优势来了。
还是先上代码
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
同样的对一组比较多的数据进行排序与对一组较少的数据进行排序实质上是一样的,所以也可以使用分治法,这里所介绍的是归并排序算法。首先是分的过程,比较简单,接下来归并的过程稍微复杂一些,它要求将两个排列好的序列再次按照大小规则排列在一起,这相对排序来说已经简化了很多,显然复杂度为$O(n)$。这里我给出的方法的代码量比较多,当然也有比较简单的写法。所以从整体来分析复杂度的话,即$T(n) = 2T(n / 2) + O(n)$,再次根据主方法可以很容易的算出$O(nlogn)$的复杂度。相对原来$O(n)$而言,是优化了一些。但是此算法也带了$O(n)$的空间开销。
这里是leetcode上关于分治法的编程练习题,可以多练习。
这里想多举一些分治法在实际情况中的具体应用。由于目前暂时还没有看到比较好的例子,待以后慢慢的积累以及更新!!
标签:
原文地址:http://www.cnblogs.com/Gru--/p/4318977.html