文章目录
- 前缀和介绍
- [LeetCode53-Maximum Subarray](https://leetcode.com/problems/maximum-subarray/submissions/)
- [LintCode44-Minimun Subarray](https://www.lintcode.com/problem/minimum-subarray/description)
- [LintCode138-Subarray Sum](https://www.lintcode.com/problem/subarray-sum/description)
- [LintCode139-Subarray Sum Closest](https://www.lintcode.com/problem/subarray-sum-closest/description)
前缀和介绍
-
假设有数组
A
且A.length = n
-
则可新建一前缀和数组
preSumArray
其长度为n+1
-
前缀和数组定义如下:
preSumArray[0] = 0
preSumArray[1] = A[0]
preSumArray[2] = A[0] +A[1]
............
preSumArray[i] = A[0] + A[1] + ........ + A[i-1]
.........................
preSumArray[n] = A[0] + A[1] + ........ + A[n-1]
-
前缀和数组有如下性质
sum(i~j) = preSumArray[j+1] - preSumArray[i]
preSumArray[j] - preSumArray[i] = Sum(i~(j - 1))
-
这个也很容易证明嘛:
preSumArray[j+1] = A[0] + A[1] + ..+ A[i-1] + ... + A[j]
preSumArray[i] = A[0] + A[1]+ .... + A[i-1]
- 二者之差等于:
A[i] + A[i+1] + .... + A[j] = sum(i~j)
-
显然,构造前缀和数组的时间和空间复杂度均为
O(n)
LeetCode53-Maximum Subarray
题意
- 给定数组,求解此数组中连续子数组之和最大的,返回这个最大值
思路
- 先求解该数组的前缀和数组
- 然后遍历前缀和数组
- 分别维护一个最大值和最小值,因为最大减最小的和最大嘛,这样遍历完成后得到一段连续数组和的最大值
代码
public int maxSubArray(int[] nums) {
if (nums == null || nums.length == 0){
return 0;
}
//0. calc the preSumArray
int n = nums.length;
int[] preSumArray = new int[n+1];
preSumArray[0] = 0;
int sum = 0;
for (int i = 0; i < n; i++) {
sum += nums[i];
preSumArray[i+1] = sum;
}
//1. find the max sum of the SubArray in the nums
//1.1 最大和的子数组一定等于 最大值减去最小值
int maxSum = Integer.MIN_VALUE;
int minSum = 0;
//1.2 遍历preSumArray
for (int i = 1; i < preSumArray.length; i++) {
maxSum = Math.max(maxSum, preSumArray[i] - minSum);
minSum = Math.min(minSum, preSumArray[i]