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]}这样的一个数组,它的的作用则是标记子数组的位置。

     

    源代码:

    #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;
    }                
    

     

    运行结果:

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

     

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

     

    在原数组中只有5个数,没有第6个数。要使重复的部分对应到前面部分,要考虑结束位置rear的取值范围,不能超过数组的长度。

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

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

     

     

    总结:

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

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

     

  • 相关阅读:
    vuecli 4使用report分析vendor.js
    vue使用 NProgress 浏览器顶部进度条
    vue项目中 configureWebpack 与 chainWebpack的区别及配置方式
    vue 项目中报错 Error: Avoided redundant navigation to current location: “/xxx”. 的解决方案
    npm中的savedev和save的区别
    vuecli 4 使用scss (配置全局scss变量)
    css如何修改滚动条样式
    vue 项目http://localhost:8080/sockjsnode/info?t=1556418283950 net:: ERR_CONNECTION_REFUSED
    java类的加载时机
    android中屏蔽键盘的2种方法
  • 原文地址:https://www.cnblogs.com/mumulucky/p/4374768.html
Copyright © 2011-2022 走看看