【IT笔试面试题整理】连续子数组的最大和

 

【试题描述】输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。

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

思路:当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。

 

【参考代码】

 

 1     public static int maxSum(int[] a) {

 2         int sum = 0;

 3         int b = 0;

 4         for (int i = 0; i < a.length; i++) {

 5             if (b < 0)

 6                 b = a[i];

 7             else

 8                 b += a[i];

 9             if (sum < b)

10                 sum = b;

11         }

12         return sum;

13     }

 

思路2:动态规划实现

/*
*问题:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。
*求所有子数组的和的最大值。要求时间负责度为O(n)。
*使用动态规划方法来实现:
*如果用函数f(i)表示以第i个数字结尾的子数组的最大和,那么我们需要求出max(f[0...n])。
*我们可以给出如下递归公式求f(i)
*     |-- array[i] 如果i==0或者f(i-1)<0
*f(i)=|
*     |-- f(i-1) + array[i] 如果f(i-1)>0
*这个公式的意义:
*   当以第(i-1)个数字为结尾的子数组中所有数字的和f(i-1)小于0时,如果把这个负数和第i个数相加,得到的结果反而不第i个数本身还要小,所以这种情况下最大子数组和是第i个数本身。
*   如果以第(i-1)个数字为结尾的子数组中所有数字的和f(i-1)大于0,与第i个数累加就得到了以第i个数结尾的子数组中所有数字的和。
*/ 

 1     public static int maxSumInSubArray(int[] array) {

 2         int[] c = new int[array.length];// 用来记录以当前元素结尾(数组就到当前元素的位置为止)的子数组的最大和

 3         int max = -1000;// 用来记录数组c[]中的最大值

 4         int start = 0;// 记录数组中子数组的最大和的开始位置

 5         int end = 0;// 记录数组中子数组的最大和的结束位置

 6         int tmp = 0;

 7 

 8         c[0] = array[0];

 9         for (int i = 1; i < array.length; ++i) {

10             if (c[i - 1] > 0) {

11                 c[i] = c[i - 1] + array[i];

12             } else {

13                 c[i] = array[i];

14                 tmp = i;

15             }

16             if (c[i] > max) {

17                 max = c[i];

18                 start = tmp;

19                 end = i;

20             }

21         }

22         System.out.println("子数组最大和的起始位置:" + start + "~" + end);

23         return max;

24     }

 

你可能感兴趣的:(面试题)