zoukankan      html  css  js  c++  java
  • 最大子数组和02

    1、题目要求:

      (1)输入一个整形数组,数组里有正数也有负数;

      (2)数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和;

      (3)如果数组A[0]……A[j-1]首位相邻,允许A[i-1],……A[n-1],A[0]……A[i-1]之和最大;

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

    2、实现思路:

      (1)先要输入一组整形数,直到输入回车结束;

      (2)分离出每一个数,按顺序存放到整形数组里;

      (3)每一个、相连续两个、三个……都是子数组,分别求出子数组的和,把最大的和输出。

    3、思路整理(实现步骤):

      (1)输入数组元素,用空格分开,输入的是字符,转化为整形数,连续的0~9字符,按所在数位进行放大求和,得出输入的整形数;

      (2)若输入的字符是空格,则将空格前的数存放入整形数组中;

      (3)按回车,输入结束,开始计算;

      (4)计算过程:

          把数组复制一遍,按顺序存放到原数组的后面,生成一个新的数组,长度为原数组的两倍,前后两部分相同;

          以下加操作全部只循环n次,以免加到重复的数;

                    从第一个数开始,依次比较大小,最大的数单独存放在num1;

          第一个数,开始,求arr[1]+arr[2]+……+arr[n],将所有和的最大值与num1 比较,最大值存入num1;

          再求arr[i]+arr[i+1]+……+arr[k],将所有和的最大值与num1 比较,最大值存入num1;

          直到arr[i] 为最后一个数为止,num1 即为子数组最大的和。

    4、源代码:

    #include <iostream>
    using namespace std;
    
    char arr[1000];//接收数据,并以字符串形式保存
    int arr1[100];//保存转换来的整数
    int arr2[200];//保存扩大两倍后的数组
    
    int k=0;//计数标志
    void chtoin()//将字符形式的数组转为整型
    {
        int i=0;
        int j=10;
    
        int num1=0;//保存每一位数字
        int num2=0;//保存数字整体
        bool flag=0;//作为正负标志
        char ch[]="#";
    
        cout<<"请输入数组(中间以空格隔开):"<<endl;
        gets(arr);
    
        strcat(arr,ch);//将#存在字符数组后,作为结束标志。
    
        for (;;)
        {
    
    
            if(arr[i]=='#')//遇到#结束,并将#前的数存入整型数组
            {
                if (flag==0)//flag为0,说明读入的数为正数
                {
                    arr1[k]=num2;
                    k++;
                }
                else//flag为1,说明读入的数为负数
                {
                    arr1[k]=0-num2;
                    k++;
                }
                break;
            }
            else
            {
                if (arr[i]==' ')//遇到空格,将空格前一个数存入整型数组
                {
                    if (flag==0)
                    {
                        i++;
                        arr1[k]=num2;
                        num2=0;
                        k++;
                    }
                    else
                    {
                        i++;
                        arr1[k]=0-num2;
                        num2=0;
                        flag=0;
                        k++;
                    }
    
                }
                else if (arr[i]=='-')//遇到-,判断为负数,将flag置位1
                {
                    i++;
                    flag=1;
                }
                else
                {
                    num1=arr[i]-'0';
                    num2=num1+num2*j;
                    i++;
                }
            }
        }
    }
    void arr1toarr2()//数组扩展函数,将数组扩展到原来的两倍
    {
        int i=0;
        for(i;i<k;i++)
        {
            arr2[i]=arr1[i];
        }
        for (;i<2*k;i++)
        {
            arr2[i]=arr1[i-k];
        }
    }
    void main()
    {
        int j=0;//作为每一轮,从第几位开始求和
        int i;//作为数组下标
        int x=0;//作为移位标志
        int y1,y2=0,y3,y4;//y1表示最大数组的首位,y2计算最大数组个数,y3保存中间过程中最大数组长度,y4保存最终长度。
        chtoin();
        arr1toarr2();
        int num1=arr2[0],num2=0,num3=0;//num1保存每一轮的最大值,num2求和,num3保存最终的最大值
        for (;;)
        {
            i=x;//已经移位到x,i作为数组下标
            for(;;)
            {
    
                num2+=arr2[i];
                y2++;
                if (num2>=num1)
                {
                    y3=y2;
                    
                    num1=num2;
                }
                if (j==k+x)
                {
                    break;
                }
                else
                {
                    if (i==k+x-1)
                    {
                        
                        num2=0;
                        j++;
                        i=j-1;
                    }
                }
                i++;
            }
            x++;
            y2=0;
            if (num3<=num1)
            {
    
                y1=x-1;
                y4=y3;
                num3=num1;
                num2=0;
                num1=0;
            }
            else
            {
                num1=0;
                num2=0;
            }
            if (x==k)
            {
                break;
            }
    
        }
        cout<<"最大子数组为:"<<endl;
        for (int h=y1;h<y1+y4;h++)
        {
            cout<<arr2[h]<<" ";
        }
        cout<<endl;
        cout<<"最大子数组和为:"<<endl;
        cout<<num3<<endl;
    }

    5、运行结果:

     6、总结分析:

           在这次的题目中,我们并没有费很多的时间,当老师提出这个问题的时候,我就想到了将原数组长度增长一倍,并复制两遍,进行计算

       遇到的问题:开始没有想到,要控制计算求和的长度,以至于把同一个数计算了两遍。。。。终于想到,数组长度变了,但求和时长度要控制在原数组的一倍长度以内。

      项目计划日志(单位:h):

      听课 编写程序 阅读相关书籍 网上查找资料   日总计
    周一 2 0 1 0.5 3.5
    周二 0 1 0.5  0 1.5
    周三  0 2 0  0 2
    周四 2 1.5  0 1.5 5
    周五  0 2 0.5 0 2.5
    周六  0 3 0  0 3
    周日          
    周总计 4 9.5 2 2 17.5

                             时间记录日志(单位:min):

    日期 开始时间 结束时间 中断时间 净时间 活动 备注
    星期一 14:00 15:50 10(课间) 100 听课 软件工程上课
      19:30 21:30 30 90 阅读、上网查资料  
    星期二 19:30 21:30 30 90 编程、阅读  
    星期三 14:00  15:00 0  60 编程 数组最大子数组之和
      19:00 20:30 30 120 编程
    星期四 14:00 15:50 10(课间) 100 听课 软件工程上课
      16:20 17:30 0 70 编程、上网查资料 数组最大子数组之和2的程序
      19:30 21:00 30 60 编程 数组最大子数组之和2的程序
    星期五 14:00 17:00 60 120 编程 数组最大子数组之和2的程序
    星期六 8:00 11:30 30(洗漱) 180 修改,调试,发布 数组最大子数组之和程序进行修改、调试、写博客并发布

    队友地址:http://www.cnblogs.com/mengyinianhua/

  • 相关阅读:
    UVa 1451 Average (斜率优化)
    POJ 1160 Post Office (四边形不等式优化DP)
    HDU 3507 Print Article (斜率DP)
    LightOJ 1427 Substring Frequency (II) (AC自动机)
    UVa 10245 The Closest Pair Problem (分治)
    POJ 1741 Tree (树分治)
    HDU 3487 Play with Chain (Splay)
    POJ 2828 Buy Tickets (线段树)
    HDU 3723 Delta Wave (高精度+calelan数)
    UVa 1625 Color Length (DP)
  • 原文地址:https://www.cnblogs.com/wangyw/p/5316319.html
Copyright © 2011-2022 走看看