题目要求:一个有N个整数元素的一维数组(A[0],A[1],···,A[n-2]、A[n-1]),这个数组当然有很多子数组,那么子数组中和最大值是多少呢?
1、子数组是连续的
2、求子数组的和,不用求子数组的具体位置
3、数组的元素时整数,所以数组可能包含有正整数、零、负整数
解法一:暴力解法,从数组的第0位开始遍历数组查找出sum[i,…,j]表示数组从第i位到底j位的和。
/*
* 求数组的子数组之和的最大值
*/
public static int MaxSum(int[] nums){
int n = nums.length;
int sum = 0;
int max = Integer.MIN_VALUE;
//这里的时间复杂度为N的三次幂
// for(int i = 0; i < n; i++){
// for(int j = i; j < n; j++){
// for(int k = i; k <= j; k++){
// sum += nums[k];
// }
// if(sum > max){
// max = sum;
// }
//每次计算完一次sum[i,...,j]的和之后,都需要将sum清零
// sum = 0;
// }
// }
//给出一个简单的优化,使得算法的时间复杂度为N的二次幂
for(int i = 0; i < n; i++){
for(int j = i; j < n; j++){
sum += nums[j];
if(sum > max)
max = sum;
}
//每次计算完一次sum[i,...,j]的和之后,都需要将sum清零
sum = 0;
}
return max;
}
解法二:采用分治的思想,将时间复杂度降到〖N*log〗_2N。考虑数组的第一个元素A[0],以及最大的一段数组(A[i],….,A[j])跟A[0]之间的关系:
1、当0=i=j时,元素A[0]本身构成和最大的一段
2、当0=i
public static int MaxSum_2(int[] nums){
int n = nums.length;
int all = nums[n-1];
int start = nums[n-1];
for(int i = n-2; i >= 0; i--){
start = max(nums[i],nums[i] + start);
all = max(start,all);
}
return all;
}
public static int MaxSum_1(int[] nums){
int n = nums.length;
int[] all = new int[n];
int[] start = new int[n];
start[n-1] = nums[n-1];
all[n-1] = nums[n-1];
for(int i = n-2; i >= 0; i--){
start[i] = max(nums[i],nums[i] + start[i+1]);
all[i] = max(start[i],all[i+1]);
}
return all[0];
}
public static int max(int x,int y){
return (x > y) ? x : y;
}