LeetCode 53. Maximum Subarray
2017-03-14 20:05
281 查看
LeetCode 53. Maximum Subarray
Description
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.For example, given the array
[-2,1,-3,4,-1,2,1,-5,4],
the contiguous subarray
[4,-1,2,1]has the largest sum =
6.
暴力枚举,时间复杂度 O(n3)
// 伪代码 for i ← 1 to n for j ← i to n sum ← a[i]+..+a[j] ans ← max(ans, sum)
class Solution { public: int maxSubArray(vector<int>& nums) { int n = nums.size(); int ans = -2147483647; for (int st = 0; st < n; ++st) for (int ed = st + 1; ed <= n; ++ed){ int sum = 0; for (int i = st; i < ed; ++i) sum += nums[i]; if (ans < sum) ans = sum; } return ans; } };
注意ans的设置。(int最小值-2147483648) 注意st, ed, i的区间。
Submission Details: 200 / 202 test cases passed. Status: Time Limit Exceeded
案例通过了,排除了死循环的嫌疑。但仍超时,说明时间复杂度太高。
三重循环,每重都是 O(n),因此时间复杂度是 O(n3) 。附加空间复杂度 O(1) 。
优化枚举,时间复杂度 O(n2)
优化代码时一般找最内层的循环,因为最内层的循环被执行的次数最多。// 伪代码 for i ← 1 to n sum ← 0 for j ← i to n sum ← sum + a[j] ans ← max(ans, sum)
class Solution { public: int maxSubArray(vector<int>& nums) { int n = nums.size(); int ans = -2147483647; for(int st = 0; st < n; ++st){ int sum = 0; for(int ed = st + 1; ed <= n; ++ed){ sum += nums[ed - 1]; if (sum > ans) ans = sum; } } return ans; } };
Submission Details: 202 / 202 test cases passed. Status: Time Limit Exceeded
(比刚才多过了两个案例,LeetCode没有做好边界检测。)
仍然超时。时间复杂度 O(n2) 。附加空间复杂度 O(1) 。
继续优化,时间复杂度 O(n)
很多算法书上给出了如下的伪代码:// 伪代码 sum ← 0 ans ← 0 for i ← 1 to n sum ← sum + a[i] ans ← max(sum, ans) if (sum < 0) sum ← 0
晦涩难懂。用去冗余的思路重写代码。
我们要求 max {a[i] + … + a[j]},设s[i] = a[0] + … + a[i],则问题转化为求max {s[j] - s[i-1]}。
若j固定(可以枚举j),s[j] = p,则max {s[j] - s[i-1]} = p - min s[i-1] (i < j)。
又,在寻找最小值的时候,有 min[0,6] = min(min[0,5] , min[6,6])。于是有下面的算法:
class Solution { public: int maxSubArray(vector<int>& nums) { int n = nums.size(); int ans = -2147483647; int sj = 0; int minSi = 0; int si = 0; for (int j = 0; j < n; ++j){ sj += nums[j]; if (si < minSi) minSi = si; if (sj - minSi > ans){ ans = sj - minSi; } si += nums[j]; } return ans; } };
Submission Details: 202 / 202 test cases passed. Status: Accepted
Runtime: 13 ms. Your runtime beats 23.20% of cpp submissions.
si和sj非常像,在for循环体的最后一句它们是相等的。可以继续优化。
变量替换,将sj替换为si + nums[j],于是有:
class Solution { public: int maxSubArray(vector<int>& nums) { int n = nums.size(); int ans = -2147483647; int minSi = 0; int si = 0; for (int j = 0; j < n; ++j){ if (si < minSi) minSi = si; if (si + nums[j] - minSi > ans){ ans = si + nums[j] - minSi; } si += nums[j]; } return ans; } };
Submission Details: 202 / 202 test cases passed. Status: Accepted
Runtime: 9 ms. Your runtime beats 57.56% of cpp submissions.
我们新设一个int变量sum,表示si - minSi,那么上面的代码就可以改成:
class Solution { public: int maxSubArray(vector<int>& nums) { int n = nums.size(); int ans = -2147483647; int sum = 0; for (int j = 0; j < n; ++j){ if (sum < 0) sum = 0; if (sum + nums[j] > ans){ ans = sum + nums[j]; } sum += nums[j]; } return ans; } };
Submission Details: 202 / 202 test cases passed. Status: Accepted
Runtime: 6 ms. Your runtime beats 98.41% of cpp submissions.
上面的代码又可以改成:
class Solution { public: int maxSubArray(vector<int>& nums) { int n = nums.size(); int ans = -2147483647; int sum = 0; for (int j = 0; j < n; ++j){ sum += nums[j]; if (sum > ans) ans = sum; if (sum < 0) sum = 0; } return ans; } };
从而与之前的伪代码一致。
相关文章推荐
- 第二周:[LeetCode]53. Maximum Subarray
- LeetCode53. Maximum Subarray
- LeetCode53. Maximum Subarray 动态规划和分治法
- leetcode: 53. Maximum Subarray
- leetcode 53. Maximum Subarray
- leetcode:53. Maximum Subarray
- Leetcode 53. Maximum Subarray
- Leetcode 53. Maximum Subarray
- leetcode--3,Longest Substring Without Repeating Characters &&53. Maximum Subarray&&String.valueOf()
- LeetCode 53. Maximum Subarray
- [LeetCode] 53. Maximum Subarray
- 个人记录-LeetCode 53. Maximum Subarray
- 【一天一道LeetCode】#53. Maximum Subarray
- LeetCode 53. Maximum Subarray
- [leetcode] 53. Maximum Subarray 解题报告
- 【LeetCode】53. Maximum Subarray
- leetcode 53. Maximum Subarray
- LeetCode 53. Maximum Subarray
- leetcode_53. Maximum Subarray
- LeetCode 53. Maximum Subarray