算法导论4.1最大子数组与分治算法

4.1求最大子数组问题

根据这17天的股票价格分析何时买进,何时买进、何时卖出可达收益最大化?

1.暴力求解

通过 对 ( n 2 ) \binom{n}{2} (2n)个日期组合处理来求解,时间复杂度为O(n)

2.变换问题

从Price的角度(值)变为Change(值的变化量),问题转化为寻找“Change数组”的和最大非空连续子数组。

3.分治方法(分解、解决、合并)

分治算法中,我们递归的求解一个问题,有三个步骤

a.分解:将原问题变为规模更小的子问题

b .解决:子问题规模足够小时停止递归,直接求解

c .合并;将子问题的解合并成原问题的解

本题中:通过Change[low,high]的中点mid=low+high)/2来划分子问题

分解:求Change[low,high]的最大子数组 → \rightarrow

子问题1.求Change[low,mid]的最大子数组;

子问题2.求 Change[mid+1,high]的最大子数组;

子问题3.求跨越mid的最大子数组

解决:当low=high时,停止递归,直接求解 → \rightarrow

最大子数组即为Change[low] (只有一个元素)

合并:取三个子问题解中的最大者

4.代码(leetcode剑指offer.42)
class Solution {
public:
  int maxSubArray(vector& nums) {
        int left=0;
        int right=nums.size()-1;
        int mid=(left+right)/2;
        return findMaxSubArry(nums,left,right);
    }
    int findMaxSubArry(vector&nums,int l,int r){
      //停止递归求解
        if(l==r)return nums[l];
        else{
          //分解为子问题
            int m=(l+r)/2;
            int lmax=findMaxSubArry(nums,l,m);
            int rmax=findMaxSubArry(nums,m+1,r);
            int mmax=findMaxCrossArry(nums,l,r,m);
          //合并
            return max(max(lmax,rmax),mmax);
        }
    }
  //求跨越m的最大子数组
    int findMaxCrossArry(vector&nums,int l,int r,int m){
        int lmax=INT_MIN;
        int lcur=0;
        int rmax=INT_MIN;
        int rcur=0;
        for(int i=m;i>=l;i--){
            lcur+=nums[i];
            if(lcur>lmax)
                lmax=lcur;
        }
        for(int j=m+1;j<=r;j++){
            rcur+=nums[j];
            if(rcur>rmax)
                rmax=rcur;
        }
        return lmax+rmax;
    }
    
};
5.分治算法分析

T ( n ) = { O ( 1 ) n = 1 2 T ( n / 2 ) + O ( n ) n > 1 T(n)=\begin{cases} O(1) &n=1 \\ 2T(n/2)+O(n)&n>1\\ \end{cases} T(n)={O(1)2T(n/2)+O(n)n=1n>1

故时间复杂度为O(nlgn)

6.改进方法(动态规划O(n))

你可能感兴趣的:(算法导论,算法,leetcode,数据结构)