zoukankan      html  css  js  c++  java
  • 3.求子数组的最大和

    问题:给出一个数组,元素有正有负,数组中连续的1个或者多个数组成1个子数组,每个子数组有1个和,求所有子数组和值的最大值,时间复杂度为O(n)

    解: 一:可以用穷举的方法求出这个最大值,只是时间复杂度是O(n^3),这中方法的代码如下

    int  dphe(int a[],int len)
    {
        int i,j;
        int **he=new int*[len];
    
        for(i=0;i<len;i++)
            *(he+i)=new int[len]();
    
        for(i=0;i<len;i++)
            for(j=0;j<len;j++)
                    he[i][j]=0;
    
        int length;
    
        for(length=0;length<len;length++)
         for(i=0;i<len-length;i++)
            for(j=i;j<=i+length;j++)
                he[i][i+length]+=a[j];
            
            
        int max=INT_MIN;
        for(i=0;i<len;i++)
            for(j=0;j<len;j++)
                if(he[i][j]>=max)
                    max=he[i][j];
    
        for(i=0;i<len;i++)
            delete [] *(he+i);
        delete he;
        return max;
    }

    这中方法没什么技巧,穷举所有的值。

    二: 观察数组可以发现,因为是要求连续的元素组成子数组,假设给定的数组是A[1,N],最后假设和最大的子数组是A[p,q],其中1<=p<=q<=N,那么我们可以得到,A[1,p-1]这个子数组的和一定是负值,否则A[1,p-1]+A[p,q]>A[p,q]就不满足A[p,q]是子数组最大的了。所以,我们可以对A进行遍历,当遇到子数组的和是负值时,就可以抛弃整个子数组了,同时要记下前面子数组的最大值,下面是用栈写的,规则如下

    1。每个元素顺序入栈,设置2个变量sum和max,sum记录在栈中的元素的总和,max记录到目前元素为止最大的子数组的和

    2。元素入栈后计算sum,若sum<0,则栈中元素全部出栈;若sum>0,则将sum和max对比,若sum>max,则更新max,否则max不变,

    代码如下,测试部分随即生成元素,并和穷举法的结果比较,最后结果都一样。

    /*
         求子数组的和,现用DP做
     */
    
    #include<iostream>
    #include<climits>
    #include<cstdlib>
    #include<time.h>
    using namespace std;
    
    int  dphe(int a[],int len)
    {
        int i,j;
        int **he=new int*[len];
    
        for(i=0;i<len;i++)
            *(he+i)=new int[len]();
    
        for(i=0;i<len;i++)
            for(j=0;j<len;j++)
                    he[i][j]=0;
    
        int length;
    
        for(length=0;length<len;length++)
         for(i=0;i<len-length;i++)
            for(j=i;j<=i+length;j++)
                he[i][i+length]+=a[j];
            
            
        int max=INT_MIN;
        for(i=0;i<len;i++)
            for(j=0;j<len;j++)
                if(he[i][j]>=max)
                    max=he[i][j];
    
        for(i=0;i<len;i++)
            delete [] *(he+i);
        delete he;
        return max;
    }
    
    /*
         下面用栈做,规则如下
         1.元素顺序入栈,保存2个变量sum和max,sum代表整个栈中元素的总和,sum代表到目前元素为止前面最大的子数组的和
         2.若sum<0,则清空整个栈
         3.若sum>max,则更新sum
    */
    
    typedef int DataType;
    #define MAX 100
    typedef struct
    {
        DataType data[MAX];
        int top;
    }Stack;
    
    Stack* init_stack(void)
    {
        Stack* s=new Stack;
        if(s)
            s->top=-1;
        return s;
    }
    
    bool empty_stack(Stack* s)
    {
        if(s->top==-1)
            return true;
        return false;
    }
    
    bool full_stack(Stack* s)
    {
        if(s->top==MAX-1)
            return true;
        return false;
    }
    
    void push_stack(Stack* s,DataType value)
    {
        if(full_stack(s))    
            return ;
        s->top++;
        s->data[s->top]=value;
    }
    
    void pop_stack(Stack* s,DataType *value)
    {
        if(empty_stack(s))
            return ;
        *value=s->data[s->top];
        s->top--;
    }
    
    void clear_stack(Stack* s)
    {
        int value;
        while(!empty_stack(s))
            pop_stack(s,&value);
    }
    
    void free_stack(Stack* s)
    {
        delete s;
    }
    
    
    int he(int a[],int length)
    {
        int i;
        Stack* s;
        int sum=0,max=INT_MIN;
    
        s=init_stack();
        for(i=0;i<length;i++)
        {
            push_stack(s,a[i]);
            sum=sum+a[i];
            if(sum<=0)
            {
                clear_stack(s);
                sum=0;
            }
            else // sum>0
            {
                if(sum>max)
                    max=sum;
            }
        }
        return max;
        free_stack(s);
    }    
    
    int main(void)
    {
        int b[]={3,-5,2,-4,7,-2,10,1};
        int c[]={-1,0,2,-1,0,4,2,-1};
        
        int a[8];
        int i,j;
    
        //比较10次
        for(j=1;j<=10;j++)
        {
            srand(time(NULL));
            for(i=0;i<8;i++)
                a[i]=rand()%200-100; //随即产生-100-100的数
            for(i=0;i<8;i++)
                cout<<a[i]<<" ";
    
            cout<<"穷举和="<<dphe(a,8)<<" ";
            cout<<"栈和="<<he(a,8)<<endl;
            sleep(1);
        }
        return 0;
    }

    三: 可以对上面代码进行精简,不用栈,对数组遍历就行。代码如下

    int he2(int a[],int length)
    {
        int i,j;
        int sum=0,max=INT_MIN;
    
    
        for(i=0;i<length;i++)
        {
            sum+=a[i];
            if(sum<=0)
                sum=0;
            else if(sum>max)
                max=sum;    
        }
        return max;
    }

    同样可以测试,结果于上面2种一样。

  • 相关阅读:
    Kubernetes 系列(八):搭建EFK日志收集系统
    Kubernetes 系列(七):持久化存储StorageClass
    Kubernetes 系列(六):持久化存储 PV与PVC
    .Net Core自动化部署系列(三):使用GitLab CI/CD 自动部署Api到Docker
    Ocelot自定义管道中间件
    生产环境项目问题记录系列(二):Docker打包镜像Nuget包因权限问题还原失败
    .Net Core 商城微服务项目系列(十四):分布式部署携程Apollo构建配置中心
    IT人该如何未雨绸缪,不断提升自己的竞争力?同时尽量避免风险?
    Session跟Cookie简单的理解
    软件测试中高级面试提问
  • 原文地址:https://www.cnblogs.com/buxianghe/p/3199520.html
Copyright © 2011-2022 走看看