leetcode #53 最大子序和 | 刷题之路第二站——动态规划类问题

题号 53

题目描述

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

示例:

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

链接:leetcode #53 最大子序和

 

解题思路1——暴力法

1- 设定两个指针 :

    maxSub 用于存储当前已经找到的连续子数组的最大和,初值为给定数组的第一个数的值

    nowSub 用于存储目前遍历的连续子数组的和,初值为0

2- 对于数组中的每一个元素 i 进行如下的循环:

    如果 nums[i] 的值比 maxSub 大,则将其赋值给 maxSub;

    如果该元素是数组中的最后一个元素,则直接返回 nums[i] 和 maxSub中较大的一个,循环结束;

    否则:

    将 nums[i] 赋值给 nowSub,令 j 指向 i 的下一个元素,当 j < nums.size() 时,进行如下的循环:

    (1)将 nums[j] 加到 nowSub

    (2)如果 nowSub 大于 maxSub,则将其值赋值给maxSub

    (3)j ++

3- 返回 maxSub

时间复杂度:O(n^2)

空间复杂度:O(1)

代码实现:

class Solution {
public:
	int maxSubArray(vector<int>& nums) {
		vector<int> ans;
		int maxSub = nums[0], nowSub = 0;;
		for (int i = 0; i < nums.size(); i++) {
			if (nums[i] > maxSub)
				maxSub = nums[i];
			if (i == nums.size() - 1) {
				return maxSub;
			}
			nowSub = nums[i];
			int j = i + 1;
			while (j < nums.size()) {
				nowSub += nums[j];
				j++;
				if (nowSub > maxSub) {
					maxSub = nowSub;
				}
			}
		}
		return maxSub;
	}
};

 

解题思路2——动态规划

Step1、2:描述问题的最优解结构特征、递归定义最优解值

对于以 nums[ i ] 结尾的所有连续子数组而言,使用 dp[ i ] 记录以 nums[ i ] 结尾的所有连续子数组中的最大和。

1- 底:dp[ 0 ] = nums[ 0 ];

2- 根据定义,dp[ i - 1 ] 存放了以 nums[ i - 1 ] 结尾的所有连续子数组中的最大和

如果 dp[ i - 1 ]  +  nums[ i ]  >  nums[ i ],  则显然 nums[ i ] 与其前面的已经计算得到的具有最大和的连续子数组共同构成新的具有最大和的连续子数组;否则,nums[ i ] 自身就是具有最大和的连续子数组【只包含 nums[ i ] 一个元素】

因此,dp[ i ] = max { dp[ i - 1] + nums[ i ], nums [ i ] }

3- 设定一个指针 max ,用于存放结果,初值为 nums[ 0 ],对于每一个元素,都比较 dp[ i ] 和 max 的值,如果前者大于后者,则将前者赋值给后者即可

4- 返回 max

 

Step3:自底向上计算最优解值

class Solution {
public:
	int maxSubArray(vector<int>& nums) {
		vector<int> dp;    //用于记录以nums[i]结尾的所有连续子数组中的最大和
		dp.push_back(nums[0]);    //底:dp[0]=nums[0]
		int ans = 0, max = nums[0];    //max用于记录结果
		for (int i = 1; i < nums.size(); i++) {    //对于给定数组中的每一个元素,进行如下循环
			if (dp[i - 1] + nums[i] > nums[i]) {    //dp[i]= dp[i-1]+nums[i]和nums[i]中较大的一个
				ans = dp[i - 1] + nums[i];
			}
			else {
				ans = nums[i];
			}
			dp.push_back(ans);
			if (ans > max) {    //max存储目前找到的所有连续子数组中的最大和
				max = ans;
			}
		}
		return max;
	}
};

时间复杂度:O(n)

空间复杂度:O(n) 

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值