您的位置:首页 > 职场人生

微软面试100题系列---求子数组的最大和

2016-09-02 04:49 295 查看

题目

输入一个整形数组,数组中有正数也有负数;数组中连续的一个或多个数组成一个子数组,每个子数组有一个和,求出所有子数组和中的最大值;

要求:时间复杂度为o(n);

实现

方法1 动态规划

思路:根据数组的最后一个元素a[n-1]与最大子数组的关系:

最大子数组包含a[n-1];

a[n-1]单独构成最大子数组;

最大子数组不包含a[n-1],那么求a[1,2,..n-1]的最大子数组和可以转换成求出a[1,2,…n-2]的最大子数组和;

All[i-1]为a[1,2,…i-1]的最大子数组和;

End[i-1]为包含a[i-1]的最大子数组和;

所以 All[i-1]=max{ a[i-1],End[i-1],All[i-2] }

代码实现

public class Num3 {

public static void main(String[] args) {
int[] a={1,-2,4,8,-4,7,-1,-5};
int res=maxSubArray(a);
System.out.println(res);
}

public static int maxSubArray(int a[]){
int n=a.length;
int[] All=new int
;
int[] End=new int
;

End[0]=a[0];
All[0]=a[0];

for(int i=1;i<n;i++){
End[i]=max(End[i-1]+a[i],a[i]);
All[i]=max(End[i],All[i-1]);
}
return All[n-1];
}

private static int max(int i, int j) {
return i>j?i:j;
}

}


方法2 优化的动态规划

思路:方法1中每次只用到End[i-1]和All[i-1],没有用到整个数组,所以可以定义2个变量保存End[i-1]和All[i-1],从而降低空间复杂度;

代码实现:

public static int maxSubArray(int a[]){
int n=a.length;
int End,All;

End=a[0];
All=a[0];

for(int i=1;i<n;i++){
End=max(End+a[i],a[i]);
All=max(End,All]);
}
return All;
}

private static int max(int i, int j) {
return i>j?i:j;
}


该方法空间复杂度o(n)

方法3

在上述方法中,End[i]=max{ End[i-1]+a[i],a[i] },对该关系分析得出:当End[i-1]<0,End[i]=a[i];所以如果某一个值使得End[i-1]<0,那么从a[i]重新计算;

代码实现:

public static int maxSubArray_2(int[] a){
int begin;//the start of the sub array
int end;// the end of the sub array

int maxSum=Integer.MIN_VALUE;
int sum=0;
int start=0;
for(int i=0;i<a.length;i++){
if(sum<0){
sum=a[i];
start=i;
}else{
sum+=a[i];
}
if(sum>maxSum){
maxSum=sum;
begin=start;
end=i;
}
}

return maxSum;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: