Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 664|回复: 0

数组(序列)的最大子段和 java实例

[复制链接]

该用户从未签到

发表于 2011-9-18 15:25:26 | 显示全部楼层 |阅读模式
问题描述:

有n个数(以下都视为整数),每个数有正有负,现在要在n个数中选取相邻的一段,使其和最大,输出最大的和。

问题分析:

看到这个问题,它是属于带“最”字的问题,其实就是一个求最优解的问题。对于这种问题的朴素算法就是枚举出每种可能,然后在其中寻找一个最优的解,然后输出。因为输出仅要求这个子段的和,因此不必再记录关于解的组成的信息。

网上有很多方法,这里选二种。

另附一个可以输出解的具体数据。
  
  一、穷举法:


import java.util.*;
public class LargestSubsegmentSum1
{
public static void main(String[] args)
{
  /**
   *从键盘输入所要求的序列的长度n
   */
  Scanner in=new Scanner(System.in);
  
  System.out.println(&quotlease enter the length of segment you want to make(输入你要求的序列的长度):");
  int n=in.nextInt();
  /**
   *从键盘输入所要求的序列,存储在a[n]中
   */
  int[] a=new int[n];
  System.out.println("Now,please enter the elements of the segment you want(请依次输入这个序列包含的元素(整数)):");
  for(int i=0;i< n;i++)
  {
   a=in.nextInt();
  }
  
        double startTime=System.currentTimeMillis();//starttime
        /**
   *求解最大子段和存在maxSum中
   */
  int maxSum=a[0];
  for(int i=0;i< n-1;i++)
  {
   int temp=a;
   for(int j=i+1;j< n;j++)
   {
    temp+=a[j];
    if(temp>maxSum)
     maxSum=temp;
   }
  }
  double endTime=System.currentTimeMillis();//endtime
  /**
   *打印输出求解结果和程序所用时间
   */
  System.out.println("The largest sub-segment sum is(最大子段和是):"+maxSum);
  System.out.println("Basic Statements take(基本语句用时) "+(endTime-startTime)+" milliseconds!");
}
}
二、动态规划
   我们令一个数组b,b[j]表示前j个元素能组成的最大和。如果b[j-1]大于零,则不管a[j]的情况, b[j-1]都可以向正方向影响,因此可以将a[j]加在b[j-1]上。如果b[j-1]小于零,则不管a[j]再大, 都会产生负影响,因此我们还不如直接令b[j]=a[j]。



import java.util.*;
public class LargestSubsegmentSum3
{
public static void main(String[] args)
{
  /**
   *从键盘输入所要求的序列的长度n
   */
  Scanner in=new Scanner(System.in);
  
  System.out.println("Please enter the length of segment you want to make(输入你要求的序列的长度):");
  int n=in.nextInt();
  /**
   *从键盘输入所要求的序列,存储在a[n]中
   */
  int[] a=new int[n];
  System.out.println("Now,please enter the elements of the segment you want(现在请依次输入这个序列包含的元素(整数)):");
  int i;
  for(i=0;i< n;i++)
  {
   a=in.nextInt();
  }
  /**
   *求解最大子段和存在maxSum中
   */
  double startTime=System.currentTimeMillis();//starttime
  int maxSum=0;
  /* 我们令一个数组b,b[j]表示前j个元素能组成的最大和。如果b[j-1]大于零,则不管a[j]的情况,
   * b[j-1]都可以向正方向影响,因此可以将a[j]加在b[j-1]上。如果b[j-1]小于零,则不管a[j]再大,
   * 都会产生负影响,因此我们还不如直接令b[j]=a[j]。
   */
  int[] b=new int[n];
  b[0]=a[0];
  for(int j=1;j< n;j++)
  {
   if(b[j-1]>0)
    b[j]=b[j-1]+a[j];
   else
   {
    b[j]=a[j];
   }
   if(b[j]>maxSum)
    maxSum=b[j];
  }
  
  double endTime=System.currentTimeMillis();//endtime
  /**
   *打印输出结果和程序运行所用时间
   */
  System.out.println("The largest sub-segment sum is(最大子段和是):"+maxSum);
  System.out.println("Basic Statements take(基本语句用时) "+(endTime-startTime)+" milliseconds!");
}
}

三:可以输出解的具体组成信息

/**
* @author Wang Ke
*
*/
/**
* 动态规划方法:若记b[j]为从a到a[j]的最大的子段和 (j是定的,“最大”指的是i从1到j-1中,a+...+a[j]最大的),
* 那么所求的max{ a+a[i+1]+...+a[j-1]+a[j] (1<=i< j<=n) } =max{ max{
* a+..+a[j] (1<=j<=n) } } =max{ b[1],...,b[n] }。 b[]由定义可知:j==1时,b[1]=a[1];
* j>1时,b[j]=max{ b[j-1]+a[j],a[j] }。
*
*/
public class MaxArray {
    /**
     * @param a
     */
    public static void prtArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a + " ");
        }
        System.out.print("\n");
    }
    /**
     * @param a1
     * @param a2
     * @return
     */
    public static int max(int a1, int a2) {
        if (a1 >= a2 || a1 == a2)
            return a1;
        return a2;
    }
    /**
     * @param n
     * @param b
     * @param a
     * @param beg
     */
    public static void setB(int n, int[] b, int[] a, int[] beg) {
        if (n == 0) {
            b[n] = a[n];
            beg[n] = n;
        } else {
            setB(n - 1, b, a, beg);
            b[n] = max(b[n - 1] + a[n], a[n]);
            if (b[n - 1] + a[n] > a[n])
                beg[n] = beg[n - 1];
            else
                beg[n] = n;
        }
    }
    /**
     * @param a
     */
    public static void maxChildArry(int[] a) {
        int b[] = new int[a.length];
        int beg[] = new int[a.length];
        b[0] = a[0];
        for (int n = 0; n < b.length; n++)
            setB(n, b, a, beg);
        int maxsum = b[getMaxElementIndex(b)];
        System.out.println("MaxSum: " + maxsum);
        PrtMaxChildArry(a, beg[getMaxElementIndex(b)], getMaxElementIndex(b));
    }
    /**
     * @param aa
     * @param beg
     * @param end
     */
    public static void PrtMaxChildArry(int aa[], int beg, int end) {
        System.out.print("The Maxmium Child-Array is: { ");
        for (int i = beg; i <= end; i++) {
            System.out.print(aa + " ");
        }
        System.out.println("}\n");
    }
    /**
     * @param b
     * @return
     */
    public static int getMaxElementIndex(int[] b) {
        // TODO Auto-generated method stub
        int maxele = 0;
        int i;
        for (i = 1; i < b.length; i++) {
            if (b[maxele] < b) {
                maxele = i;
            }
        }
        return maxele;
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] a = { 1, 2, -1, 1, 3, 2, -2, 3, -1, 5, -7, 3, 2, -2, 4 - 5 };
        prtArray(a);
        maxChildArry(a);
    }
}

运行:

C:\ww>java MaxArray
1 2 -1 1 3 2 -2 3 -1 5 -7 3 2 -2 -1
MaxSum: 13
The Maxmium Child-Array is: { 1 2 -1 1 3 2 -2 3 -1 5 }
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-10 23:30 , Processed in 0.389518 second(s), 47 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表