zoukankan      html  css  js  c++  java
  • 结对(求数组的最大子数组和)

    题目:

      返回一个整数数组中最大子数组的和。

    要求:

      输入一个整形数组,数组里有正数也有负数。

      数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。

      如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大。

      同时返回最大子数组的位置。

      求所有子数组的和的最大值。

    (我主要负责程序分析,代码编程;张金负责代码复审,代码测试计划。)

     

    思路:

      与第一次的不同之处,只在于首尾相连,构成了一个环。思路差不多,我们构造了三个数组:(A)arr[]为原数组;(B)Max[]保存以每个元素为头的所有子数组的和的最大值;(C)arrCopy[]将原数组头尾相连构造的新的一维数组。它们的关系如下:

    max[0]为{arr[0]、arr[0]+arr[1]、...、arr[0]+arr[1]+...+arr[n-1]+arr[n]}中的最大值;

    max[1]为{arr[1]、arr[1]+arr[2]、...、arr[1]+arr[2]+...+arr[n]+arr[1]}中的最大值;

    ......

    max[n-1]为{arr[n-1]、arr[n-1]+arr[n]、...、arr[n-1]+arr[n]+...+arr[n-3]+arr[n-2]}中的最大值;

    max[n]为{arr[n]、arr[n]+arr[1]、...、arr[n]+arr[1]+...+arr[n-2]+arr[n-1]}中的最大值。再比较max数组,从中找到最大值。

    arrCopy[]为{arr[1]、arr[2]、...、arr[n]、arr[1]、...、arr[n-1]}这样的一个数组,它的的作用则是标记子数组的位置。

    <span style="font-family: Microsoft YaHei; font-size: 16px;">#include<iostream.h>

    #include<stdlib.h>

    #define AMOUNT 100

    int main()

    {

        int arr[AMOUNT];

        int arrCopy[AMOUNT];

        int max[AMOUNT];

        int i,j;

        int n;

        int head,rear;      //子数组的开始,结束

        int mount,amount;

        cout<<"input mount: ";

        cin>>mount;

        while(mount<=0)

        {

        cout<<"illegal input! Again :";

        cin>>mount;

        }

        amount=2*mount-1;

        for(i=0;i<mount;i++)

        {

        try

        {

                n=rand()%2;

                if(n==0)

            {

            arr[i]=rand()%100;

            arrCopy[i]=arr[i];

            max[i]=arr[i];

            }

            else

            {

            arr[i]=-rand()%100;

            arrCopy[i]=arr[i];

            max[i]=arr[i];

            }

            }

        catch(long int e)

        {

            cout<<"Long Inter=ger Exception!"<<endl;

            }

        }

        for(i=0;i<mount;i++)

        {

        cout<<arr[i]<<"  ";

        if((i+1)%10==0)

        {

            cout<<endl;

        }

        }

        for(i=mount;i<amount;i++)

        {

        arr[i]=arr[i-mount];

        arrCopy[i]=arr[i];

        }

        for(j=0;j<mount;j++)

        {

            for(i=j+1;i<j+mount;i++)

            {  

            arr[j]=arr[j]+arr[i];

            if(max[j]<arr[j])

            {

            max[j]=arr[j];

            rear=i+1;

            if(rear>mount)

            {

                rear=rear-mount;

            }          

            }

            }

        }

        for(i=0;i<mount;i++)

        {

            if(max[0]<max[i])

        {

                max[0]=max[i];

            head=i+1;

        }  

        }

        cout<<endl;

        cout<<"从第"<<head<<"个数"<<arrCopy[head-1]<<"开始"<<endl;

        cout<<"到第"<<rear<<"个数"<<arrCopy[rear-1]<<"结束"<<endl;

        cout<<"子数组和的最大值为: "<<max[0]<<endl;

        return 0;

    }               

    </span>

    运行结果:

    (1)首先由于没有仔细的考虑,在提示输入数组长度的时候随意输了负数,导致程序不能正常执行,经过修改,能对不符合的数据类型发出错误提示,并且重新输入。

     

    (2)有图可以看到,定义的数组长度为5,和最大的子数组是由第5个数循环至第1个数组成的,但却显示的是arrCopy[]数组中的第6个数,位置不正确。

    (3)经过修改,能正确找到环的结束位置。

     

    (4)但是我们自己手动输入的数都很小,所以最后改动:只输入数组长度(截图测试为10),数值随机产生。

    总结:

      看到题目最先想到的是数据结构中的链表结构,但是很快就把这个思路放弃,感觉用链表比较麻烦,听了课上三位同学的思路,大家的观点其实都是把数组构成一个环状结构,或者构成一个新的一维数组,接着就跟第一次求最大和一样。开始犯难的是在怎么确定子数组的起始元素和结尾元素上,下标的记录是很关键的,因为在我们的算法中,运用递归会不断覆盖原数组的值,造成所有子数组求完和之后,原数组的值发生了改变,而无法返回最大子数组的位置,既然如此,能像到的方法就是把子数组复制一遍,最后定位时可以使用。最后还是数据测试的问题,手动输入具有很大的主观意识,所以还是使用随机数测试比较能发现问题。

      感觉现在能解决一些问题了,但方法还是想初学者那般,很多类似时间、空间复杂度那些都没有考虑。

  • 相关阅读:
    c++ 中 pair 的 使用方法
    初窥c++11:lambda函数及其用法
    HDU2089-不要62
    算法训练 K好数
    点评删除和编辑
    事务
    SQL Function 自定义函数
    常用CSS实例
    分页显示数据
    开发教程指南
  • 原文地址:https://www.cnblogs.com/xiaojin123/p/4376517.html
Copyright © 2011-2022 走看看