题目链接
力扣:leetcode.cn/problems/ma…
牛客:www.nowcoder.com/practice/17…
下面的解题使用的是牛客的OJ,和力扣稍微有点区别的就是需要自己写入数组。
题目描述
给定一个长度为 n 的数组,数组中的数为整数。
请你选择一个非空连续子数组,使该子数组所有数之和尽可能大,子数组最小长度为1。求这个最大值。
输入描述:
第一行为一个正整数 n ,代表数组的长度。
第二行为 n 个整数 ai,用空格隔开,代表数组中的每一个数。$∣a~# 连续子数组最大和
题目链接
力扣:leetcode.cn/problems/ma…
牛客:www.nowcoder.com/practice/17…
下面的解题使用的是牛客的OJ,和力扣稍微有点区别的就是需要自己写入数组。
题目描述
给定一个长度为 n 的数组,数组中的数为整数。
请你选择一个非空连续子数组,使该子数组所有数之和尽可能大,子数组最小长度为1。求这个最大值。
输入描述:
第一行为一个正整数 n ,代表数组的长度。
第二行为 n 个整数 ,用空格隔开,代表数组中的每一个数。
输出描述:
连续子数组的最大之和。
示例1
输入:
8
1 -2 3 10 -4 7 2 -5
输出:
18
说明:经分析可知,输入数组的子数组[3,10,-4,7,2]可以求得最大和为18
题目解析
此题当然有暴力解法,嵌套循环,但是本题考的知识点并不是它,如果面试官出的这题,我们应该使用动态规划来解。
1.状态表示
我们要找到最大的子数组之和,也就需要从左往右进行遍历元素,在以 i 下标为结尾时,列出所有以 i 为结尾的子数组,寻找出最大子数组之和。
例如上图,当数组下标 i = 4的时候,此时的子数组有5种情况,但是最大的子数组为[7,0,8],结果为15
然后我们创建dp表,也就是一个数组,这个数组用于存储i所在位置的最大值。
例如,将i = 4的最大值记录到dp[4],所以dp[4] = 15。
所以我们的状态表示:
dp[i] :以 i 为结尾的最大子数组和。
那此处如果是第一次了解动态规划的同学就会有疑问,为什么表示以i为结尾的最大子数组的和呢
在我的理解,我们的状态表示就是需要 直接展现出 变量在 此刻 的结果。而状态转移方程就是让“此刻”动起来。
2.状态转移方程
我们先看看方程有几种情况
状态表示——dp[i] :以 i 为结尾的最大子数组和。
如上图的dp表和数组arr所对应的情况,
i = 0时,子数组只有[3],所以dp[0] = 3;
当 i = 1时,子数组有两种情况,[3, -4]和[-4],最大值为 - 1。而[3, -4]其实就是dp[0] + arr[1]的这种情况。所以dp[1] = dp[0] + arr[1] = -1。因为dp[0]是以0为结尾的最大的子数组之和,所以最大的(前提dp[i]为正数)加上arr[1]就是dp[1]的最大数。
当i = 2时,子数组有3种,也就是图上黑线画出的[3, -4, 7]、[-4, 7]、[7],此时最大的结果为7,并不是dp[1] + arr[2],因为dp[1]为负数。
所以我们状态表示方程就出来了,但在写代码的时候为了方便,我们不需要判断dp[i - 1]的值是否大于0,而是直接比较这两种情况谁大就行。
3.编写代码