- 1 题目
- 2 解决方案
- 2.1 思路
- 2.3 时间复杂度
- 2.4 空间复杂度
- 3 源码
- 4 另解——贪心算法
题目:最大子数组(Maximum Subarray)
描述:**给定一个整数数组,找到一个具有最大和的子数组,返回其最大和。每个子数组的数字在数组中的位置应该是连续的。子数组最少包含一个数 **
lintcode题号——41,难度——easy
样例1:
输入:nums = [−2,2,−3,4,−1,2,1,−5,3] 输出:6 解释:符合要求的子数组为[4,−1,2,1],其最大和为 6。
样例2:
输入:nums = [1,2,3,4] 输出:10 解释:符合要求的子数组为[1,2,3,4],其最大和为 10。2 解决方案 2.1 思路
常规思路可以采用暴力法,使用两个序号,两重循环遍历出所有子数组来找到最大的,时间复杂度为O(^2)。
这题可以只使用O(n)的复杂度来解决,引入一个前缀和的概念,即从头部开始到该位置的前一位置的数值累加和,最小前缀和即为之前所有位置的前缀和中最小的那个,要找到最大的子数组的值,只要通过当前位置的累加值减去之前的最小前缀和即可,在一次循环内即可完成累加求和以及更新最小前缀和的操作。
时间复杂度为O(n)。
2.4 空间复杂度空间复杂度为O(1)。
3 源码细节:
- 一边求当前累加和,一边求当前位置往前的最小前缀和,以当前位置结尾的最大子数组的值即为两者之差。
C++版本:
int maxSubArray(vector4 另解——贪心算法&nums) { // write your code here if (nums.empty()) { return 0; } int maxSum = INT_MIN; int sum = 0; // 当前累加和 int minPrefixSum = 0; // 最小的前缀和,不用记录下标 for (int i = 0; i < nums.size(); i++) { sum += nums.at(i); maxSum = max(sum - minPrefixSum, maxSum); // 累加和-最小前缀和=子数组可能的最大值 minPrefixSum = min(sum, minPrefixSum); // 更新最小前缀和 } return maxSum; }
细节:
- 用贪心的思想也可以解,思路是一旦发现前面的子串为负,无法为整个串带来正收益,则抛弃该子串,重新开始计算。
C++版本:
int maxSubArray(vector&nums) { // write your code here if (nums.empty()) { return 0; } int result = INT_MIN; int curSum = 0; for (int i = 0; i < nums.size(); i++) { curSum += nums.at(i); result = max(curSum, result); curSum = max(curSum, 0); // 子串只取大于0的 } return result; }



