天天看点

《算法技术手册》一3.6.2 分治

分治通常是将一个规模为n的问题划分成两个独立的子问题,其中每个子问题的规模约为n/2。大部分时候分治策略是递归形式的,并且会有简单易懂的基本条件用于结束递归。此外,在计算出两个较小问题的解之后,还必须要有一些计算来根据子问题的解计算出原问题的解。

下面来看一个例子:求包含n个数的数组中的最大元素。例3-2展示了如何将原问题分解成两个子问题并通过递归求解。通常,最大值一般是两个子集各自的最大值中比较大的那一个。仔细观察尾递归触发的条件,即子集中只有一个元素vals[left]返回。

例3-2:递归分治求数组中最大值

/* 开始使用递归函数 /

public static int maxElement(int[] vals) {

if (vals.length == 0) {

}

return maxElement(vals, 0, vals.length);

/** 计算vals[left, right)的最大元素

注意vals[right]并不在计算之列 */

int maxElement(int[] vals, int left, int right) {

if (right - left == 1) {

// 计算子问题

int mid = (left + right) / 2;

int max1 = maxElement(vals, left, mid);

int max2 = maxElement(vals, mid, right);

// 合并处理:从子问题的解中得到当前问题的解

if (max1 > max2) { return max1; }

return max2;

例3-2中分治算法的时间复杂度是O(n),因为子问题解的合并处理在常数时间内就能完成。如果这一步需要O(n)时间,那么整体的时间复杂度将会上升至O(n log n)。当然,我们也可以不用分治算法,直接遍历数组并且记下当前所找到的最大值。所以,就当是一个小小的提示吧:分治算法并不总是最快的。

继续阅读