问题:
给定一个整数数组,数组种可能存在正数、负数和零。求所有子数组的和的最大值;
例如:
如果输入的数组是{1,-2,3,10,-4,7,2,-5},和最大的子数组为{3,10,-4,7,2},
那么输出该子数组的和为18
思想:
解决方法类似于上面的求子数组最大积,只是当前位置处子数组的最大和可能是前面的max+当前位置值与当前位置值得最大值;
代码:
public class MaxSum {
public static void main(String[] args) {
int[] arr = {6,-3,-2,7,-15,1,2,2};
System.out.println(getMaxSum(arr));
}
public static int getMaxSum(int[] arr)
{
if(arr == null)
return -1;
if(arr.length == 0)
return 0;
int max = arr[0];
int result = arr[0];
for(int i = 1;i < arr.length;i++)
{
max = max+arr[i];
max = Math.max(max, arr[i]);
result = Math.max(max, result);
}
return result;
}
}
那么如果想要输出这个最大和的子数组的话,我们需要修改代码,只需要增加一个标志数组用来记录这个子数组的开始和结束位置即可了;
public class MaxSum {
public static void main(String[] args) {
int[] arr = {1,-2,3,10,-4,7,2,-5};
int[] result = getMaxSumStartAndEnd(arr);
if(result != null)
print(arr, result[0], result[1]);
}
/**
* 获得子数组和最大的子数组的开始和结束下标
* @param arr
* @return
*/
public static int[] getMaxSumStartAndEnd(int[] arr)
{
int[] result = new int[2];
int start = 0;//开始下标
int end = 0;//结束下标
if(arr == null)
return null;
if(arr.length == 0)
{
result[0] = 0;
result[1] = 0;
return result;
}
int max = arr[0];//临时最大值
int tempMax = arr[0];//临时值
int realMax = arr[0];//最后真正的最大值
for(int i = 1;i < arr.length;i++)
{
tempMax = max+arr[i];
max = Math.max(tempMax, arr[i]);
if(max > realMax && max == tempMax)
{
//表示当前最大值是加上当前元素后得到的,那么就需要修改end下标值了
end = i;
}else if(max > realMax && max == arr[i])
{
//表示当前最大值是当前元素,那么需要修改start下标值
start = i;
}
realMax = Math.max(max, realMax);
}
result[0] = start;
result[1] = end;
return result;
}
public static void print(int[] arr,int start,int end)
{
for(int i = start;i <= end;i++)
{
System.out.print(arr[i]+" ");
}
}
}