分治法
所谓分治法,就是把问题不断分割变小,常见的是把数组分割为两部分,然后分别计算,将大问题变成小问题。
问题分析方向

这一类问题主要用的是递归的方法,所以时间复杂度普遍为O(nlogn)
对时间复杂度的分析

样例分析
接下来分析最大子数组问题
问题分析
分解问题
求最大子数组无非就是求数组内某段连续的数相加,那么通过分治的思想,我们把问题拆开。
将一个数组变成两个数组,然后分别找两个数组中最大的子数组,然后再比较大小。
这么一想就会觉得问题简单了不少。但是仔细一想不对啊,要是最大子数组在两个部分中都有怎么办呢?
于是这样我们就把问题分解为三个部分:

解决问题
对于仅位于两边的子数组来说好解决
- 在分解后的数组长度大于1的时候继续递归
- 要是到了递归尾了,那就直接输出最后剩下那一个数组元素就好了。
但是要是是中间那种情况怎么办呢?
这个好解决,要这么想,既然是经过最中间的元素,那么最大子数组里面必然包括最中间那个元素,那么直接从中间向两边遍历就好了。
通过不断累加计算寻找两边是否有更好的情况。

合并问题
对于某一个子数组来说,递归所返回的子数组就是最大子数组,其中返回的子数组就是目前这个某数组的最大子数组,因为返回的子数组就是从他的左边选出来的数组和右边选出来的子数组以及中间选出来的子数组中挑选的最大数组。
同理对于他的父数组来说也是这样。应该是类似于数学归纳法的想法。
对代码的设想
中间部分的处理
- 伪代码(来自算法导论)

- C语言实现
mid_message find_mid(int A[], int low, int mid, int high)
{
mid_message midx;
int left_sum = -inf;
int sum = 0;
for(int i = mid ; i >= low ; i--)
{
sum = sum + A[i];
if (sum > left_sum)
{
left_sum = sum;
midx.max_left = i;
}
}
int right_sum = -inf;
sum = 0;
for(int j = mid + 1 ; j <= high ; j++)
{
sum = sum + A[j];
if (sum > right_sum)
{
right_sum = sum


3395

被折叠的 条评论
为什么被折叠?



