最大子数组问题的分治

一、最大子数组问题

1、实际问题背景

我们进行股票交易的时候,可以估计一短时间的股票估值,我们总是喜欢最低价买入,最高价卖出,寻求利益最大化。在现实中我们很有可能遇到最高价在前,最低价在后的情况,这就需要我们不能简单的找最大值和最小值,而是需要对于一段时间的股票价值求最大交易利益。

2、最大和子数组问题

我们把实际问题可以抽象出来:

我们寻找一段时间的最大利润,那就可以抽象出一个数组。然后我们定义第i ii个数据代表第i天和第i − 1 i-1i−1天的价格差,数组的第一个数据是第2天的价格与第1天价格的差值。那么问题就转化为寻找数组的最大和的非空连续子数组。我们称这个问题为最大和子数组问题。

3、暴力求解

我们很容易设计出一种暴力求解办法,可以直接计算出每一种组合的和,然后得到和最大的组合以及最大和。时间复杂度为Ω(n^2 )。

二、分治思想

分治法:1、把一个问题分成(同类的)几个子问题。2、递归地解决(征服)每个子问题。3、将子问题的解决方案组合成整体解决方案。

分治法问题的关键在于:如何去分以及分成什么样的子问题是可以解决的。

1、如何去分:

对于数组arr的切片[low, high],可以选择其中间结点mid,则可以将数组分为[low, mid]、[mid+1, high]、则可以认为答案在一下三种情况中:

1.中间结点左边的最大子数组
2.中间结点右边的最大子数组
3.包含中间结点的最大子数组

2、什么样的子问题可以解决:

1.对于情况1,2,则可以继续往下细分。

2.对于情况3,由于本身就是细分的结果,所以需要进行直接求解

3.细分下去最终会进入low = high的情况,也就是子数组只有一个元素

3、对于子数组只有两个元素(low与high)的情况

1.在该情况下,我们已知中间结点的左右边最大子数组就是该元素.

2.对于情况3:将两个元素相加后得到sum,将sum与其他两个值比较,最大的那个对应的子数组作为该字数的最大子数组,并记录。

三、伪算法求解

1 left_sum = -∞         //左数组的最大子数组的值

2 sum=0    //数组的值

3 for i = mid downto low   //从中间结点开始向低结点加上去。

4        sum = sum+A[i]

5         if sum>left_sum           //这里是找到左半部分最大和,以及最大值所对应的数组

6                left_sum = sum

7                max_left = i //left_sum与max_left分别是左半部最大和以及最大和对应的数组的左边界

8 right_sum = -∞

9 sum=0 

10 for j =mid +1 to high

11       sum = sum+A[j]

12       if sum>right_sum                         //这里是找到右半部分最大和,以及最大值所对应的数组                                                                      的最右边的数的索引,分别用right_sum和max_right记录

13              right_sum = sum

14              max_right = j

15 return (max_left,max_right,left_sum+right_sum)   //返回左部最大值,右部最大值以及二者和中最大的值

四、关于分治思想的一些问题

1、分治思想的时间复杂度:T(n)

当n=1时,T(n)=θ(1)

当n>1时,根据2.2的情况分法,情况1,2可以继续细分下去即时间复杂度为T(n/2),情况3需要遍历子数组的每一个元素所以时间复杂度为θ(n):

T(n)=2T(n/2)+θ(n)

综上所述:T(n)=2T(n/2)+θ(n)  /  T(n) = θ(n lgn)

2、分治思想的优点

分治策略相比于传统的多重循环解决策略往往有执行时间少的优势,这个优势的来源于分治策略所用的思想:空间换时间与树的数据结构

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