一 .最大子数组和
题目链接:53. 最大子数组和 - 力扣(LeetCode)
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
方法1:动态规划
遍历列表,我们让列表每个位置存放的 “包含这个位置的子数组中最大的和”
包含这个位置元素的子数组 有两种可能:
1.它本身单独一个数 :【它本身】
2.它和前面的数组成子数组 : 【包含前一个位置 的子数组的最优情况 】+ 【它本身】
如 【1 ,-1 , 1】遍历后变成【1,0,1】
我们再初始化一个 最大值 max_sum实时与最新情况比较,记录出现的情况中的最大值
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
# 动态规划方法
n = len(nums)
if n == 1:return nums[0]
max_sum = nums[0]
for i in range(1,n):
nums[i] = max(nums[i] + nums[i-1],nums[i])
if nums[i] > max_sum:max_sum = nums[i]
return max_sum
二.子数组的最大绝对值
题目链接:1749. 任意子数组和的绝对值的最大值 - 力扣(LeetCode)
给你一个整数数组 nums
。一个子数组 [numsl, numsl+1, ..., numsr-1, numsr]
的 和的绝对值 为 abs(numsl + numsl+1 + ... + numsr-1 + numsr)
。
请你找出 nums
中 和的绝对值 最大的任意子数组(可能为空),并返回该 最大值 。
abs(x)
定义如下:
- 如果
x
是负整数,那么abs(x) = -x
。 - 如果
x
是非负整数,那么abs(x) = x
。
雷区:下面的做法是错的
# 错误做法
class Solution:
def maxAbsoluteSum(self, nums: List[int]) -> int:
n = len(nums)
if n == 1: return abs(nums[0])
max_abs = abs(nums[0])
nums[0] = abs(nums[0])
for i in range(1,n):
nums[i] = max(abs(nums[i] + nums[i-1]),abs(nums[i]))
max_abs = max(max_abs,nums[i])
return max_abs
一开始写太快我就写成这样,但是这种写法纯在巨大的逻辑错误。绝对值与 求 最大/最小值 不同
最大最小值中 : -9 < 0 < 1 纯粹的相加结果是一个方向一直推进的
绝对值: 变成了 0 < 1< | -9 | ,单纯的相加结果的-9 ,摇身一遍成了最大值。
所以 我们不能再一次遍历中直接去比较。因为单纯的相加结果比较 跟 最大值比较 的结果不一定相同
所以 我们分别求出 最大值和最小值,最后返回绝对值大者即可
正确写法:
class Solution:
def maxAbsoluteSum(self, nums: List[int]) -> int:
# 动态规划方法,求出最大值和最小值,返回两者中绝对值较大者
n = len(nums)
if n == 1:return abs(nums[0])
nums_min = nums[:]
# 原来的列表中的值在求极值之一时就改变了,求解剩下的极值不能再用原列表
# 所以在开始之前先复制列表
max_sum = nums[0]
min_sum = nums[0]
for i in range(1,n):
nums[i] = max(nums[i] + nums[i-1],nums[i])
if nums[i] > max_sum:max_sum = nums[i]
for i in range(1,n):
nums_min[i] = min(nums_min[i]+nums_min[i-1],nums_min[i])
if nums_min[i] < min_sum : min_sum = nums_min[i]
return max(abs(max_sum),abs(min_sum))