vlambda博客
学习文章列表

动态规划(一)最大子序和



最大子序和


原题链接:https://leetcode-cn.com/problems/maximum-subarray/

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


示例 1:

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

输出:6

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




这个一道可以使用动态规则比较典型的题目。

由于是连续子数组,故在遍历数组时,之前数组加起来的和大于0,之后加上任和大于0的数,都将使值增大。遍历到数组的某一位(大于0)时,其最大值就是前一个最大值加上本身或者就是本身。

例题中:

状态转移方程为 f(i) = Math.max(f(i-1)+nums[i],nums[i])

f(1) = Math.max(f(0) + 1,1) = -1

f(2) = Math.max(f(1) - 3, -3) = -2

f(3) = Math.max(f(2) + 4, 4) = 4

f(4) = Math.max(f(3) -1, -1) = 3

f(5) = Math.max(f(4) + 2, 2) = 5

f(6) = Math.max(f(5)+ 1, 1) = 6

f(7) = Math.max(f(6) - 5, -5) = 1

f(8)= Math.max(f(7)+ 4, 4) = 5


其状态转移方程是 f{i) = Math.max(f(i+1)+nums[i] , nums[i])






题目代码


         

有了状态转移方程,动态规划的题目就比较好写,代码如下:

 public int maxSubArray(int[] nums) { if(nums == null || nums.length == 0){ return 0; }
// 假设前一位的最大值为 0 int pre = 0; // 假设整个子序列最大值是数组的第一位 int max = nums[0]; // 假设当前最大值是 0 int cur = 0; // 遍历数组 for (int num : nums) { // 前一位的最大值是 cur = Math.max(pre+num,num); // 保存遍历过程中的最大值 max = Math.max(max,cur); // 下一个的最大值为当前的值,继续遍历 pre = cur; } return max;    }
动态规划(一)最大子序和



小结



动态规划的题目重点在于如何找到它的状态转移方程。另外这题还能使用贪心算法进行解题。