一个数组中找出连续子向量的最大和 分治算法 扫描算法O(n)

算法设计艺术

输入具有n个整数的向量data,输出向量的任意连续子向量的最大和,
当所有输入都是负数时,综合的最大子向量是空向量,总和为0;
例如输入10个数
31,-41,59,26,-53,58,97,-93,-23,84

输出
data[2..6]的和 187
59+26+(-53)+58+97

其中最高效的是扫描算法O(n)
分治算法O(n*logn)
基本算法是O(n^2)

/* description: 从一个数组中找出连续子向量的最大和 参考<<编程珠玑>> author:Jason date:20160515 */
#include<stdio.h>
#include<iostream>
using namespace std;

//最简单的方法 复杂度 O(n^3)
int maxsum_fun1(int data[],int len)
{
    int maxsofar=0;
    int sum=0;

    for(int i=0;i<len;i++)
    {
        for (int j=i;j<len;j++)
        {
            sum=0;
            for (int k=i;k<j;k++)
            {
                sum+=data[k];
            }
            maxsofar=max(maxsofar,sum);
        }
    }
    return maxsofar;

}

//复杂度 O(n^2)
int  maxsum_fun2(int data[],int len)
{
    int maxsofar=0;
    int sum=0;

    for(int i=0;i<len;i++)
    {
        sum=0;
        for (int j=i;j<len;j++)
        {
            sum+=data[j];
            maxsofar=max(maxsofar,sum);
        }
    }

    return maxsofar;
}

//分治算法 O(n*logn)
int maxsum_fun3(int data[],int l,int u)
{
    int sum=0;
    if (l>u) 
    {
        return 0;
    }
    if (l==u)
    {
        return max(0,data[l]);
    }

    //find max crossing left
    int m=(l+u)/2;
    int lmax=0;
    sum=0;
    for (int i=m;i>=l;i--)
    {
        sum+=data[i];
        lmax=max(lmax,sum);
    }

    //find max crossing right
    int rmax=0;
    sum=0;
    for(int i=(m+1);i<=u;i++)
    {
        sum+=data[i];
        rmax=max(rmax,sum);
    }

    int max_medium=rmax+lmax;
    int max_left=maxsum_fun3(data,l,m);
    int max_right=maxsum_fun3(data,m+1,u);
    //chose one max 
    int max_result=max(max_medium,max_left);
    max_result=max(max_result,max_right);
    return max_result;
}
//扫描算法 O(n)
int maxsum_fun4(int data[],int len)
{
    int maxsofar=0;
    int maxending=0;
    for (int i=0;i<len;i++)
    {
        maxending=max(maxending+data[i],0);
        maxsofar=max(maxending,maxsofar);
    }
    return maxsofar;
}
int main()
{
    int data[]={31,-41,59,26,-53,58,97,-93,-23,84};
    int len=10;
    cout<<"data:"<<endl;
    for(int i=0;i<len;i++)
    {
        cout<<data[i]<<" ";
    }
    cout<<endl;

    cout<<"--------------------------------"<<endl;
    int max_result_1=   maxsum_fun1(data,len);
    cout<<"fun1 O(n^3) \nmax_result_1:"<<max_result_1<<endl;


    cout<<"--------------------------------"<<endl;
    int max_result_2=maxsum_fun2(data,len);
    cout<<"fun2 O(n^2) \nmax_result_2:"<<max_result_2<<endl;
    cout<<"--------------------------------"<<endl;
    int max_result_3=maxsum_fun3(data,0,len-1);
    cout<<"fun3 O(n*logn) \nmax_result_3:"<<max_result_3<<endl;
    cout<<"--------------------------------"<<endl;
    int max_result_4=maxsum_fun4(data,len);
    cout<<"fun4 O(n) \nmax_result_4:"<<max_result_4<<endl;
    return 0;

}

结果如下:
一个数组中找出连续子向量的最大和 分治算法 扫描算法O(n)_第1张图片

你可能感兴趣的:(分治算法,最大子向量和,扫描算法)