程序设计思想
此次题目是在上次题目的基础上演变而来的,所以首先需要解决上次的问题。一个数组中为有正有负的整数,需要求出该数组所有子数组的和的最大值。需要明白一点,一个子数组的和最大,那么这个子数组的前n-1个数之和一定会大于0 。如果前n-1个数之和小于0,那么第n个数便可以独立成一个子数组而且该子数组的和大于原来子数组的和。所以在遍历数组时,用一个变量存放遍历到当前数字的和,如果当前的和大于0,则继续遍历,否重下一个数字重新计算和。这样便可以求出一个数组中最大子数组之和了。此次的问题是要将数组首尾连接起来求最大子数组之和,所以只需要遍历数组两次就行了。
出现的问题:
如果只设定为将数组遍历两次,那么有所求子数组之和包含的元素个数会大于原来数组的元素个数。
解决方案:
数组是循环的,所以我们需要求出从第1个元素到第n个元素的之间的最大子数组之和,第2到到第1个元素,第3个到第2个元素……第n个到第n-1个元素之间的最大子数组之和,然后从之中选出最大的值。但是这样算法时间复杂度将不再是O(n),而是O(n2)。
程序源代码:
1 public class MaxValueOfSubArray { 2 3 public static void main(String[] args) { 4 // TODO Auto-generated method stub 5 int array[] = {2,3,-4,5,-3,-8,7,1,-2}; 6 int len = array.length; 7 int sum = 0; 8 for(int i = 0; i < len; i++) 9 { 10 //求出从i到i+len之间的最大子数组值,如果i+len大于数组长度,则对数组长度取余数 11 int temp = getMaxSubArray(array, i, i+len); 12 //更新最大子数组的值 13 if(temp > sum) 14 sum = temp; 15 System.out.print(array[i]+" "); 16 } 17 System.out.println("最大子数组之和为:"+sum); 18 } 19 20 public static int getMaxSubArray(int[] array,int begin,int end) 21 //求数组array在下标begin和end之间的最大子数组之和,如果下标越界,则取下标对数组长度的余数 22 { 23 int len = array.length; //求出数组的长度 24 if(len <= 0) //如果数组不是有效的数组,则返回一个无效的值 25 return -1111111111; 26 int sum = array[begin]; //sum用来存放子数组之和的最大值,首先赋值为第一个数 27 int mark = sum; //mark用来标识当前子数组之和,初始化为第一个数 28 for(int i = begin+1; i < end; i++) 29 { 30 if(mark > 0) //如果当前子数组之和大于0,则mark加上当前的数字 31 mark += array[i%len]; 32 else //如果当前子数组之和小于等于0,则mark从当前数字重新计数 33 mark = array[i%len]; 34 if(sum < mark) //更新sum的值 35 sum = mark; 36 } 37 return sum; 38 } 39 40 }
结果截图:
总结:
学习不可能一蹴而就,这是一个长期的积累过程。实践是学习最好的手段,交流是学习的重要的工具。遇到问题不能置之不理,多和同学交流讨论,取长补短才能不断提高自己的水平。编程需要有耐心,调试过程中不要怕麻烦。课外可以多看相关书籍,了解更多的编程技巧。