首页 > leetcode-53 最大子序和

leetcode-53 最大子序和

题目描述如下:

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],

输出: 6

解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

方法一(暴力求解):

针对数组中的每一个元素,穷举所有的可能性,从中找到以当前元素结尾的最大的元素即可;

穷举的过程中维护一个最大值,然后遍历完整个数组,那么最大值即为整个数组的最大值。

实现如下:

class Solution { 
public:int maxSubArray(vector<int>& nums) { if(nums.size() == 1) return nums[0];int res = nums[0];for (int i = 1;i < nums.size(); ++i) { int pre = _maxSubArray(nums,i);res = max(res,pre);}return res;}
private:int _maxSubArray(vector<int> &nums, int index) { if(index == 0) { return nums[0];}int pre = _maxSubArray(nums, index - 1);int res = max(nums[index] + pre, nums[index]);return res;}
};

由于是递归的过程,该方法显然会超时,所以引入如下动态规划的方法

方法二(动态规划):

在暴力求解的过程,我们找到以当前元素为结尾的最大子序列和,然后遍历所有的元素,找到每个元素结尾的最大子序列和中的最大的即为整个数组的最大子序列和

那么可以得到如下状态转移方程

dp[i] = max(dp[i-1] + nums[i], nums[i])

这里需要注意,子序列是连续的数组,如果发现dp[i-1] + nums[i] < nums[i],那么此时数组的起始元素应从nums[i]开始

实现如下:

int maxSubArray(vector<int>& nums) { if(nums.size() == 1) return nums[0];int res = nums[0];vector<int> dp(nums.size(), 0);dp[0] = nums[0];for (int i = 1;i < nums.size(); ++i) { dp[i] = max(dp[i-1] + nums[i], nums[i]);res = max(res, dp[i]);}return res;
}

由于以上过程使用的dp数组,空间复杂度是O(n)

但是针对本题,计算过程中仅仅只需要保存当前状态和前一个状态的值,即两个状态;可以简化本题的空间复杂度到O(1)

int maxSubArray(vector<int>& nums) { if(nums.size() == 1) return nums[0];int res = nums[0];int dp0 = nums[0];int dp1;for (int i = 1;i < nums.size(); ++i) { dp1 = max(dp0 + nums[i], nums[i]);res = max(res, dp1);dp0 = dp1;}return res;
}

更多相关:

  • 题目:调整数组顺序使奇数位于偶数前面 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。 示例: 输入:nums = [1,2,3,4] 输出:[1,3,2,4] 注:[3,1,2,4] 也是正确的答案之一。 提示: 1 <= nums.length <=...

  • 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例: 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1]...

  • 题目描述: 给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。 示例 1: 输入: [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] 有最大乘积 6。 示例 2: 输入: [-2,0,-1] 输出: 0 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。 该题目...

  • WinForm绘制带有升序、降序的柱形图   private void HuiZhiTu( string strPaiXu){//初始数据int[] nums = { 150, 89, 200, 60, 70, 90 };if (strPaiXu == "升序"){//冒泡排序for (int i = 0; i <...

  •         Apache POI是一个开源的利用Java读写Excel,WORD等微软OLE2组件文档的项目。        我的需求是对Excel的数据进行导入或将数据以Excel的形式导出。先上简单的测试代码:package com.xing.studyTest.poi;import java.io.FileInputSt...

  • 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 要取得a到b之间的...

  • 利用本征图像分解(Intrinsic Image Decomposition)算法,将图像分解为shading(illumination) image 和 reflectance(albedo) image,计算图像的reflectance image。 Reflectance Image 是指在变化的光照条件下能够维持不变的图像部分...

  • 题目:面试题39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题: cl...

  • 题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树:      5     /    2   6   /  1   3示例 1: 输入: [1,6,3,2,5] 输出...

  • 问题链接 LeetCode 7 题目解析 给定一个32位有符号整数,求其反转数字。 解题思路 如果是简单反转的话,那这道题就太简单了。题目要求判断溢出问题,32位int类型的范围是-2147483648~2147483647。数字反转过后是有可能超出范围的,此时应该返回0。 最简单的想法是,反转结果用long long表示,其范围远超...

  • 这两天在看小程序的地图,写写笔记记录一下 小程序官方文档提供的方法 https://mp.weixin.qq.com/debug/wxadoc/dev/api/location.html 腾讯地图提供的jssdk http://lbs.qq.com/qqmap_wx_jssdk/qqmapwx.html 根据提示使用腾讯地图jssdk...

  • 1.链接地址: http://bailian.openjudge.cn/practice/2739/ 2.题目: 总时间限制:1000ms内存限制:65536kB描述给定两个正整数a和b。可以知道一定存在整数x,使得x <= logab < x + 1输出x输入第1行是测试数据的组数n,每组测试数据占2行,分别是a和b。每组测试数据之...