一个数组中找出连续子向量的最大和 分治算法 扫描算法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;

}

结果如下:
这里写图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值