leetcode hot 100 53 最大子数组和
题目链接
53. 最大子数组和
题目描述
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组是数组中的一个连续部分。
示例 1:
1 2 3
| 输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
|
示例 2:
示例 3:
1 2
| 输入:nums = [5,4,-1,7,8] 输出:23
|
提示:
1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
**进阶:**如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。
分析及AC代码
好简单的dp,无需多言
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Solution { public: int maxSubArray(vector<int>& nums) { int n = nums.size(); vector<int>dp(n); int ans = nums[0]; for(int i=0;i<n;i++){ if(i == 0){ dp[i] = nums[i]; }else{ dp[i] = max(dp[i-1] + nums[i], nums[i]); } ans = max(ans, dp[i]); } return ans; } };
|
再思考一下进阶的分治做法
感觉用分治写有点多此一举,就当锻炼思维了。核心在于 可以将 区间分为 左区间,右区间,还有一个跨区间。左区间和右区间的起点和终点容易确定。中间跨区间由中心向两边枚举即可。时间复杂度 O(nlogn) ,比 dp 的O(n) 更久。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| class Solution { public: int find_max(int l, int r, vector<int>& nums) { if (l == r) { return nums[l]; } if (r - l + 1 == 2) { return max(max(nums[l], nums[r]), nums[l] + nums[r]); } int mid = (l + r) >> 1; int l_subarr_max = find_max(l, mid, nums); int r_subarr_max = find_max(mid, r, nums); int across_max = nums[mid]; int l_p = mid - 1, r_p = mid + 1; int l_sum = nums[l_p], r_sum = nums[r_p]; int l_max = l_sum, r_max = r_sum; while (l_p > l) { l_p--; l_sum += nums[l_p]; l_max = max(l_max, l_sum); } while (r_p < r) { r_p++; r_sum += nums[r_p]; r_max = max(r_max, r_sum); } across_max = across_max + l_max + r_max; return max(across_max, max(l_subarr_max, r_subarr_max)); }
int maxSubArray(vector<int>& nums) { return find_max(0, nums.size() - 1, nums); } };
|