本文正在参与「Python主题月」,概况查看 活动链接

标题描绘

这是 LeetCode 上的 剑指 Offer 42. 连续子数组的最大和 ,难度为 简略

Tag : 「线性 DP」

输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求悉数子数组的和的最大值。

要求时间数组指针复杂度为O(n)O(n)

示例1:

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

提示:

  • 1 <=arr.length <= 10510^5
  • -100 <= arr[i] <= 100

动态规划

这是一道简略线java模拟器性 DP电脑截图快捷键 题。

界说 f[i]f[i] 为考虑以 nums[i]nums数组公式[i] 为完毕的子数组的最大值。

不失一般性的考虑 f[i]f[i] 怎样转移。

明显关于 nums[i]nums[i] 而言,以它为leetcode高频100题完毕的子数组分两种状况:

  • num[i]num[i] 本身作为独立子数组:f[i]=nums[i]f[ileetcode会员] = nums[i]
  • num[i]num[i] 与之前的数值组成子数组leetcode题库app,由所以子数组,其只能接在 nums[i−1]nums[i – 1],即有:f[i]=f[i−1]+nums[i]f[i] = f[i – 1] + nums[i]

毕竟 f[i]f[i] 为上述两种状况取 max⁡max 即可:

f[i]=max⁡(nums[i],f[i−1]+nums[i])f[i] = max(nums[i], f[i – 1] + nums[i])

Java 代码:

class Solution {
public int maxSubArray(int数组和链表的差异[] nums) {
int n = nums.length;
int[] f = new int[n];
f[0] =leetcode会员 nums[0];
injava环境变量装备t ans = f[0];
for数组长度 (int i = 1数组的界说; i < n; i++) {
f[i] = Math数组初始化.max(nums[i], f[i - 1] + nums[i]);
ans = Math.max(复杂度排序ans, f[i]);
}数组和链表的差异
rleetcode题库appeturn ans;
}
}

Python 3 代码:

class Solution:
def maxSubArray(self, nums: List[i数组公式nt]) -> ileetcode会员nt:
n = len(nums)
f = [0] * n
ans = f[0] = nums[0]
for i in range(1, n):
f[i] = max(nums[i], f[i - 1] + nums[i])
aleetcode每日一题ns = max(ans, f[i])
return ans
  • 时间复杂度复杂度排序O(n)O(n)
  • 数组长度间复杂度:O复杂度英文(n)O(n)

空间优化

调查状况转移方程,咱们发现 f[i]f[i] 明晰值依赖于 f[i−1]f[i – 1]

因而咱们能够运用「有限变量」或许「翻滚数组」的方法,将空间优化至 O(1)O(javaee1)

Java 代码:

class Solution {
public int maxSubArray(int[] nums) {
int n = nums.length;
int max = nums[0], ans = max;
for (int i = 1; i < n; i++) {
m数组词ax = Math.max(nums数组词[i], max + nleetcode在线编程网站ums[i]);
ans = Math.max(ans, max);
}
ret电脑怎样衔接wifiurn an复杂度符号s;
}
}
class Solution {
public int maxSubA复杂度排序rray(int[] nums) {
int n = nums.length数组的界说;
int[] f = new int[2];
f[0] = nums[0];
int ans = f[0];
for (int i = 1; i < n; i++) {
int a = i & 1, b = (i - 1) &amp复杂度怎样核算的; 1;
f[aleetcode会员]电脑键盘功能基础知识 = Math.max(nums[i], f[b] + nums[i]);
ans = Math.max(a复杂度符号ns, f[a]);
}
retleetcode中文官网urn ans;
}
}

Python 3java面试题 代码:

class Solution:
def max复杂度最高的是SubArray(self, nums: List[int电脑怎样恢复出厂设置]) -> int:
n = len(nums)
ans = curMax = nums[0]
for i in rleetcode会员ange(1, n):
curMax = max(nums[i], curMax + nums[leetcode下载i])
aLeetCodens = max(ans, curMax)
return ans
class Solutjavascription:
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
ans数组和链表的差异 = nleetcode下载ums[0]
f = [数组初始化ans, 0]
for i in range(1, n):
a, b = i & 1, (i - 1) & 1
f[a] = max(nums[i], f[b] + nums[i])
ans = max(ans, f[a])
return ans
  • 时间复杂度:O(n)复杂度剖析O(n)
  • 空间复杂度:O(1)O(1)

拓宽

一个有意思的拓宽是,将 加法 替换成 乘法

标题变成 152. 乘积最大子数组(中等)。

又该怎样数组初始化考虑呢?

一个朴素的主见,仍然是考虑界说 f[i]f[i] 代表以 nums[i]nums[i] 为完毕的最大值,但存在「负负得正」取得最大值的状况,java环境变量装备光维护一个前缀最大值明显是不可的,咱们能够多引进一维 g[i]g[i] 作为前缀最小值。

其他剖析与本题同理。

Java 代码:

class Solution {
public i复杂度怎样核算的nt maxProduct(int[] nums) {
int n = nums.length;
int[] g = new int[n + 1]; // 考虑前 i 个,作用最小值
int[] f = new int[n + 1]; // 考虑前 i 个,作用最大值
g[0] = 1;
f[0] = 1;
int ans = nums[0];
for (java难学吗int i = 1; i <= n; i++) {
int x = nums[i - 1];
g[i] = Math.mi数组长度n(x, Math.mijava模拟器n(g[i - 1] * x, f数组指针[i -数组 1] * x));
f[i] = Math.mleetcode在线编程网站ax(x, Math.mleetcode题库ax(g[i - 1] * x, f[i - 1] * x));
ans = Math.max(ans, f[i]);
}
return ans;
}
}
class Solution {
public int maxProduct(int[] nums) {
int n = nums.length;
int min = 1, max = 1;
int ans = nums[0];
for (int i = 1; i <= n; i++) {
int x = nums[电脑开不了机怎样办i - 1];
int nmijava模拟器n = Math.min(x, Mat数组初始化h.min(min * x, max * x));
int nmax = Math.max(x, Math.max数组词(min * x, max * x));
min = n电脑截图快捷键min;
max = nmax复杂度最优;
ans = Math.max(ans, max);
}
return ans;
}
}

Python 3 代码:


class Solution:
def maxProduct(self, nums: List[int]) -> int:
n = len(numsLeetCode)
g = [0] * (n + 1) # 考虑前 i 个,作用最小值
f = [0] * (n + 1) # 考虑前 i 个,作用最大值
g[0] = f[0] = 1
ans = nums[0]
for i in range(1, n + 1):
x = nums[电脑蓝屏i - 1]
g[i] = min(x, min(g[i-1] * x, f[i-1] * x))
f[i电脑] = max(x, max(g[i-1] * x, f[i-leetcode题库1] * x))
ans = max(a数组长度ns, max(f[i], g[i]))
return ans

最终

这是咱们「刷穿 LeetCode」系列文章的第 No.剑指 Offer 42 篇,系列开复杂度o(1)什么意思始于 2021/01/01,截止于开端日 LeetCode 上共有 1916 道标题,部分是有锁题,咱们将先把悉数不带锁的标题刷完。

在这个系列文章里面,除了说明解题思路以外,还会尽可能给出最为简练的代码。如果触及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的库javascript房:github.com/SharingSour… 。

在库房地址里,你能够看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。