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


    要求

    1.输入一个整型数组,数组里有正数也有负数。

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

    3.求所有子数组的和的最大值。要求时间复杂度为O(n)

    思路及源代码

      看到要求时,有点读不懂题。我以为是求数组中连续的数的和,比如-1 3 15 6 7 -9里求的是6+7=13,很显然我理解错了,真正题意求的是3+15+6+7=31。

      首先不考虑时间复杂度为O(n),可以使用以下方法求得最大子数组的和。

    package test;
    
    import java.util.Scanner;
    
    public class FindMaxArray {
        
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int[] a = new int[10];
            for(int i=0;i<10;i++)
                a[i] = sc.nextInt();
            sc.close();
            int[] max = new int[10];    //用于存储以对应位置起始的所有子数组和的最大值
            int t;
            for(int i=0;i<10;i++) {
                t=0;
                for(int j=i;j<10;j++) {
                    t += a[j];
                    if(max[i] < t)
                        max[i] = t;
                }
            }
            t=0;
            for(int i=0;i<10;i++)
                if(t<max[i])
                    t=max[i];
            System.out.println(“最大子数组的和为” + t);
        }
    }

      本来以为所有最大子数组必定包含最大数,但是后来找到了一组反例,-12 13 -2 -13 3 11 1 -1 1 -1,最大子数组和为3+11+1=15,此时并未包含最大数13。后来发现如果以数块为基本单位,那么最大子数组必定包含最大数块,并且以最大数块为基点左右蔓延。

    package test;
    
    import java.util.Scanner;
    
    public class FindMaxArray {
        
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int[] a = new int[10];
            for(int i=0;i<10;i++)
                a[i] = sc.nextInt();
            sc.close();
            int[] b = new int[10];  //数块数组
            b[0] = a[0];
            int j=0,max,maxnum=0;
            for(int i=1;i<10;i++) {
                if(a[i]<0 && b[j]>0)
                    b[++j] = a[i];
                else if(a[i]>0 && b[j]<0)
                    b[++j] = a[i];
                else if(a[i]<=0 && b[j]<0)
                    b[j] += a[i];
                else if(a[i]>=0 && b[j]>0)
                    b[j] += a[i];
            }
            if(b[0]<=0 && b[1]==0) {    //所有数均小于等于0时
                max=a[0];
                for(int i=1;i<10;i++)
                    if(max<a[i])
                        max=a[i];
                System.out.println("最大子数组的和为:" + max);
                return;
            }
            max=b[0];
            for(int i=0;i<=j;i++)
                if(max<b[i]) {
                    max=b[i];
                    maxnum=i;
                }
            int t=0;
            for(int i=maxnum;i<=j-2;i+=2) {    //从最大数块所在位置向右运算
                t=t+b[i+1]+b[i+2];         //最大数块右方的数块和,如果存在大于0的,则可以加入最大子数组和的运算
                if(t>0) {
                    max+=t;
                    t=0;
                }
            }
            t=0;
            for(int i=maxnum;i>=2;i-=2) {    //从最大数块所在位置向左运算
                t=t+b[i-1]+b[i-2];         //最大数块左方的数块和,如果存在大于0的,则可以加入最大子数组和的运算
                if(t>0) {
                    max+=t;
                    t=0;
                }
            }
            System.out.println("最大子数组的和为:" + max);
        }
    }

     运行结果截图

  • 相关阅读:
    Xcode 构建规则
    创建带阴影,有圆角的UIView的正确方式
    EffectiveC#12,13,14--成员初始化
    EffectiveC#11--选择foreach循环
    EffectiveC#9--明白几个相等运算之间的关系
    EffectiveC#8--确保0对于值类型数据是有效的(初始化问题)
    NET基础课--泛型(NET之美)
    NET基础课-- 类型基础(NET之美)
    EffectiveC#7--选择恒定的原子值类型数据
    EffectiveC#6--区别值类型数据和引用类型数据
  • 原文地址:https://www.cnblogs.com/dream0-0/p/10506548.html
Copyright © 2020-2023  润新知