题目要求:
n题目:返回一个整数数组中最大子数组的和。
n要求:
n输入一个整形数组,数组里有正数也有负数。
n数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
n求所有子数组的和的最大值。要求时间复杂度为O(n)。
设计思想(借鉴王教授上课所讲内容)
1. 想要得到最大子数组的和,首先得生成一个自定义长度的含有正负号的范围自定义的数组。
1.1 用到的函数:随机数生成函数。
1.2 函数具体内容,代码:
static int array[]=new int[10000]; static void rand(int number,int fw) { for(int i=0;i<number;i++) { int m=-1; Random rd1=new Random(); m=rd1.nextInt(2); Random rd=new Random(); if(m==1) { array[i]=rd.nextInt(fw); } else { array[i]=-(rd.nextInt(fw)); } } }
这样便把生成的随机数存到array的int类型的数组里了;
2.然后就是实现查找最大子数组的和的部分:
2.1 实现思路:
先生成一个和array类型相同长度相同的数组array1,用于存储循环查找时的最大值,maxval用于返回的最大值
从array数组的第一个数值开始查找,如果array中的数值大于零就将其与前面的数值进行加和并存到刚刚开辟的数组array1中
每次循环,都比较目前的maxval与array1[i]中的值,那个比较大就把值赋给maxval
直到循环完毕。
2.2 此部分实现代码:
class Find { public static int find(int[] array) { int array1[] = new int[array.length]; array1[0] = array[0]; int maxVal = array[0]; for(int i = 0;i < array.length - 1;i++) { //如果第i+1个元素的前i个元素之和大于0就把这i个元素的和加到第i+1个元素上面 即前i个元素对第i+1个元素有贡献 if(array1[i] > 0) { array1[i+1] = array1[i] + array[i+1]; } //如果第i+1个元素的前i个元素之和小于0不加 即前i个元素对第i+1个元素没有贡献 else { array1[i+1] = array[i+1]; } //更新最大值 maxVal = Math.max(maxVal,array1[i+1]); } return maxVal; }
3. 最后将数组的生成以及最大值的查找写到主函数内,完成程序编写
4. 程序源代码:
package e; import java.math.*; import java.util.Random; import java.util.Scanner; @SuppressWarnings("unused") public class Array { /** * @param args */ static int array[]=new int[10000]; static void rand(int number,int fw) { for(int i=0;i<number;i++) { int m=-1; Random rd1=new Random(); m=rd1.nextInt(2); Random rd=new Random(); if(m==1) { array[i]=rd.nextInt(fw); } else { array[i]=-(rd.nextInt(fw)); } } } public static void main(String[] args) { // TODO Auto-generated method stub @SuppressWarnings("resource") Scanner a=new Scanner(System.in); System.out.println("请输入随机生成的数组的长度以及取值范围(只写正数)"); int numbers=a.nextInt(); int Fws=a.nextInt(); rand(numbers,Fws); int max = Find.find(array); for(int i = 0;i < numbers;i++) { System.out.print(array[i]+" "); if(i%5==0) { System.out.print("\n\n"); } } System.out.println(); System.out.println("最大子数组之和为:"+max); } } class Find { public static int find(int[] array) { int array1[] = new int[array.length]; array1[0] = array[0]; int maxVal = array[0]; for(int i = 0;i < array.length - 1;i++) { //如果第i+1个元素的前i个元素之和大于0就把这i个元素的和加到第i+1个元素上面 即前i个元素对第i+1个元素有贡献 if(array1[i] > 0) { array1[i+1] = array1[i] + array[i+1]; } //如果第i+1个元素的前i个元素之和小于0不加 即前i个元素对第i+1个元素没有贡献 else { array1[i+1] = array[i+1]; } //更新最大值 maxVal = Math.max(maxVal,array1[i+1]); } return maxVal; } }
5.程序运行结果截图:
02
程序总结:
这次编写程序曾尝试不用王教授所讲解的思路去做,(本人的错误思路:先查找生成的数组的所有连续正数,然后吧下标信息存入另一个数组中,最后把原数组的所有连续正数加和,比较这些和求出最大值。 但是这种想法会导致错误,比如连续正数之间出现了负数但后边又是连续正数,显然加上这个负数会比只求连续正数的和大得多,这是我考虑所欠缺的地方)。
经验:程序的思路很重要,该如何实现每一步,要先想好再编写,否则会做许多无用功。