Leetcode算法初学——动态规划算法“最大子序和”
题目:
给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。难度(简单)。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
题解:
拿到题的第一想法是暴力搜索,两个嵌套循环遍历搜索循环比较最大值,最后返回最大值
1 class Solution { 2 public: 3 int maxSubArray(vector<int>& nums) { 4 int max=INT_MIN; 5 for(int i=0;i<nums.size();i++) 6 { 7 int sum=0; 8 for(int j=i;j<nums.size();j++) 9 { 10 sum=sum+nums[j]; 11 if(sum>max) 12 { 13 max=sum; 14 } 15 } 16 } 17 return max; 18 } 19 };
成功通过检测:
可以看到,虽然成功通过了检测,但是显示执行用时过长,时间复杂度为O(n2),于是转换思路用动态规划,先确定动态规划转移方程,可以想到,当n=1时,最大值为n1,当n=2时,最大值要么为n1,要么为n2要么就为n1+n2,与爬楼梯很相似,尽管爬楼梯的边界是固定的,而最大子序和要比爬楼梯略微复杂一些,它可以从中间任何地方取值,但是原理相似,最小子序和就是取前n个数的最大值与后一个数以及与后一个数的和作比较取最大值,所以只要用一个if循环,里面加两个判断就可以做出来,并且因为只用取一个值而不用列出情况,可以只设常数空间而不用设立数组,空间复杂度为O(1),时间复杂度为O(n):
1 class Solution { 2 public: 3 int maxSubArray(vector<int> &nums) 4 { 5 int Max = INT_MIN; 6 int db; 7 db = nums[0]; 8 Max = db; 9 for (int i = 1; i < nums.size(); i++) 10 { 11 if (db + nums[i] > nums[i]) 12 { 13 db = db + nums[i]; 14 } 15 else { db = nums[i]; } 16 if (db > Max) 17 { 18 Max = db; 19 } 20 } 21 return Max; 22 } 23 24 };
成功通过检测:
可以看出,相比较嵌套循环暴力搜索,时间节省了很多,这就是动态规划算法的好处。