剑指offer-连续子数组的最大和

题目:连续子数组的最大和

题目描述:HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

 

 方法一:

一般思路分析:这个题其实就是求在一个数组中,连续子数组的最大和。思路其实比较清晰,由于数组中元素有正有负,所以我要尽量让大的正数多一点,小的负数少一些。我们可以从数组中第一个元素开始相加,如果加完之后是负的,那我们可以直接将前面的舍弃,从当前这个数开始重新继续加,如果是正的则保留,用同样的规律一直往后相加,始终保证我前面算进去的一连串数的和为正值,那么最终和必然会越加越大。

代码:

 1 public class Solution {
 2     public int FindGreatestSumOfSubArray(int[] array) {
 3         if (array.length<=0||array==null)return 0;
 4         int sum=0;
 5         int max=Integer.MIN_VALUE;
 6         for(int i=0;i<array.length;i++){
 7             if(sum<0)sum=array[i];
 8             else sum+=array[i];
 9             if(sum>max)max=sum;
10         }
11         return max;
12     }
13 }

方法二:

使用动态规划:从方法一的描述中我们也可以看出,最大和的连续子数组的子数组必然也是部分最大和,也就是说我们最终得到的最大和必然可以有更小的子数组的部分最大和组成。方法一所干的事就是把有正有负的数组分成多个段,将其中为正的连续的段连起来,和必然就会越来越大,如果某个段相加后为负数则放弃它找新的段。动态规划就是从开始段找到当前段的最大值,然后往后添加元素,不断更新最大值,最终得到的必然是子数组的最大值。

我们用dp[i]表示以array[i]结尾的子数组的最大和

dp[i]=max(array[i],dp[i-1]+array[i])

代码:

 1 public class Solution {
 2     public int FindGreatestSumOfSubArray(int[] array) {
 3         if (array.length<=0||array==null)return 0;
 4         int sum=array[0];
 5         int max=array[0];
 6         for(int i=1;i<array.length;i++){
 7            
 8             max=Math.max(array[i],max+array[i]);
 9             sum=Math.max(sum,max);
10         }
11         return sum;
12     }
13 }

 

posted @ 2018-07-23 22:17  pathjh  阅读(190)  评论(0编辑  收藏  举报