题目:输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。
示例:
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
题目分析:
我们试着从头到尾逐个累加示例数组中的每个数字。
- 初始化子数组的和为数组的第一个元素 sum = -2 (sum = array[0]); 子数组的和的最大值为当前的子数组和 max = -2 (max = sum);
- 从数组的第二个元素开始,直到数组的最后一个元素为止,分别进行试探。循环体内部:
- 添加数组中的第二个元素之前,需要判断当前和(sum = -2)是否大于零。如果小于零,说明加到后面的数据中,会拖后腿,通过赋值完成丢弃。sum = array[1] = 1 即可。得到最新的sum后需要和max比较,如果最新的sum大于max,则将sum赋值给max, max = sum = 1。
- 添加数组中的第三个元素之前,需要判断当前和(sum = 1)是否大于零。如果大于零,则添加第三个元素。sum = sum + array[2] = 1 + (-3) = -2 即可。得到最新的sum后需要和max比较,如果最新的sum小于max,max = 1不变。
- 添加数组中的第四个元素之前,需要判断当前和(sum = -2)是否大于零。如果小于零,说明加到后面的数据中,会拖后腿,通过赋值完成丢弃。sum = array[3] = 4 即可。得到最新的sum后需要和max比较,如果最新的sum大于max,则将sum赋值给max, max = sum = 4。
- 添加数组中的第五个元素之前,需要判断当前和(sum = 4)是否大于零。如果大于零,则添加第五个元素。sum = sum + array[4] = 4 + (-1) = 3 即可。得到最新的sum后需要和max比较,如果最新的sum小于max,max = 4不变。
- 添加数组中的第六个元素之前,需要判断当前和(sum = 3)是否大于零。如果大于零,则添加第六个元素。sum = sum + array[5] = 3 + 2 = 5 即可。得到最新的sum后需要和max比较,如果最新的sum大于max,则将sum赋值给max, max = sum = 5。
- 添加数组中的第七个元素之前,需要判断当前和(sum = 5)是否大于零。如果大于零,则添加第七个元素。sum = sum + array[6] = 5 + 1 = 6 即可。得到最新的sum后需要和max比较,如果最新的sum大于max,则将sum赋值给max, max = sum = 6。
- 添加数组中的第八个元素之前,需要判断当前和(sum = 6)是否大于零。如果大于零,则添加第八个元素。sum = sum + array[7] = 6 + (-5) = 1 即可。得到最新的sum后需要和max比较,如果最新的sum小于max,max = 6不变。
- 添加数组中的第九个元素之前,需要判断当前和(sum = 1)是否大于零。如果大于零,则添加第九个元素。sum = sum + array[8] = 1 + 4 = 5 即可。得到最新的sum后需要和max比较,如果最新的sum小于max,max = 6不变。
- 遍历完所有元素后,得出最大值为 6,对应的子数组就是 {4,-1,2,1}。
Java代码:
/**
* 输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。
* 求所有子数组的和的最大值。
*
* 要求时间复杂度为O(n)。
*
* 示例1:
* 输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
* 输出: 6
* 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
*/
public class Offer42 {
public static void main(String[] args) {
int[] array1 = {1, -2, 3, 10, -4, 7, 2, -5};
int[] array2 = {-2, -8, -1, -5, -9};
int[] array3 = {2, 8, 1, 5, 9};
int[] array4 = {};
int result1 = maxSubArray(array1);
int result2 = maxSubArray(array2);
int result3 = maxSubArray(array3);
int result4 = maxSubArray(array4);
System.out.println(result1);
System.out.println(result2);
System.out.println(result3);
System.out.println(result4);
}
public static int maxSubArray(int[] nums) {
// 判断数组是否为空。
if (nums==null || nums.length==0){
// System.out.println("数组为空");
return 0;
}
int sum = nums[0];
int max = sum;
for (int i = 1; i < nums.length; i++) {
if (sum<=0){
sum = nums[i];
}else {
sum += nums[i];
}
if (sum>max){
max = sum;
}
}
return max;
}
}
【注】
(1):leetcode 等平台只要我们完成一个函数即可,本人初出茅庐,为了巩固基本知识,故自己补充了部分代码,用于练手。本代码也许存在漏洞,望高手赐教。感谢!
(2):本题最好的解法应该是利用动态规划。