最近一直在刷动态规划的相关的题目,刷到两道模板差不多的题目,都是需要判断列表中满足需求的一部分,这样有个滑动窗口的感觉,如果用滑动窗口写感觉很难的样子,但是用牺牲空间的动态规划写就能将每一个状态都存起来,如果下次需要比对这个状态直接调用就可以,十分方便。
难度中等5196
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1] 输出:1
示例 3:
输入:nums = [5,4,-1,7,8] 输出:23
思考:这一题主要方面就是存储一个二维的列表存储每个地方的状态,dp。其中dp[i][j]为i到j的范围时候,是否满足要求,或者这部分的值是多少。
模板是。
class Solution:
def f(self,str):
n = len(str)
dp = [[0] * n for _ in range(n)]
for i in range(n):
# 将每个字符位置进行初始化
dp[i][i] = True
for L in range(n): # 遍历的是长度
for i in range(n): # 遍历的是起始位置
j = L + i # 结束位置
if j >= n:break # 当越界的时候直接结束
# 下面就是匹配判断
# 根据状态函数来写的
if 不断更新状态
return dp
这就是一个基础的模板,然后看下这道题怎么做。
最大数和,需要判断的也就是当前的数,和前面一个最大的数值做判断,
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
res = 0
if n == 1:return nums[0]
dp = [[0] * n for _ in range(n)]
for i in range(n):
dp[i][i] = nums[i]
for L in range(n):
for i in range(n-1):
j = L + i
if j >= n:
break
dp[i][j] = max(dp[i+1][j]+nums[i],nums[i])
if dp[i][j] > res:
res = dp[i][j]
return res
但是这一块的内容有问题,只能176/190.
看了下题解,给的解释有几种方法可以做,分治,动态规划,而且他们给出的动态规划根本没有这么复杂,主要思路就是,当前节点纳入还是不纳入最大数列和当中,如果不纳入,dp当前值就为nums[i]。纳入,dp就为前面最大的。
遍历整个字符,寻找较大的数值,然后动态判断最大的数值。
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
pre, maxans = 0,nums[0]
dp = [0] * len(nums)
for i in range(len(nums)):
dp[i] = max(dp[i-1]+nums[i],nums[i])
maxans = max(dp[i],maxans)
return maxans
难度中等5542
给你一个字符串 s
,找到 s
中最长的回文子串。
示例 1:
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd" 输出:"bb"
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
maxlen = 0
star = 0
dp = [[False] * n for _ in range(n)]
for i in range(n):
dp[i][i] = True
for L in range(n):
for i in range(n):
j = L + i
if j >= n:break
if s[i] != s[j]:
dp[i][j] = False
else:
if j - i < 3:
dp[i][j] = True
else:
dp[i][j] = dp[i+1][j-1]
# 不断更新
if dp[i][j] and j - i + 1 > maxlen:
maxlen = j - i + 1
star = i
return s[star:star+maxlen]