代码随想录算法训练营day44| 1143.最长公共子序列 1035.不相交的线 53. 最大子序和 392.判断子序列
学习资料:https://programmercarl.com/1143.最长公共子序列.html#算法公开课
动态规划系列之子序列
其实有些用贪心也可解
学习记录:
1143.最长公共子序列(dp[i][j]是代表的i-1和j-1为止的两个片段的最长公共子序列,原因是为了更好的初始化;比如当dp[0][0]代表的到-1和-1的两个片段,那肯定不存在,所以两个片段无交集,值为0,否则还得仔细考虑两者交集)
点击查看代码
class Solution(object):
def longestCommonSubsequence(self, text1, text2):
"""
:type text1: str
:type text2: str
:rtype: int
"""
# dp[i][j]代表num1中到i-1和nums2中到j-1为止的两段的最长公共子序列长度
# 构造二维dp数组
dp = [[0]*(len(text2)+1) for _ in range((len(text1)+1))]
# 初始化也是0,跳过
# 开始遍历
for i in range(1, len(text1)+1):
for j in range(1, len(text2)+1):
if text1[i-1] == text2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1 # 由左上角的值加1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1]) # 由左边和上边的值确定
return dp[len(text1)][len(text2)] # 右下角的值
1035.不相交的线(与最长公共子序列的解法一致)
点击查看代码
class Solution(object):
def maxUncrossedLines(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: int
"""
# 与最长公共子序列解法一致
# dp[i][j]是nums1的i及之前和nums2的j及之前的最长公共子序列
dp = [[0]*(len(nums2)+1) for _ in range(len(nums1)+1)]
# 初始化也是把左边和上边设置为0
# 开始遍历
for i in range(1, len(nums1)+1):
for j in range(1, len(nums2)+1):
if nums1[i-1] == nums2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
return dp[len(nums1)][len(nums2)]
53.最大子序和(当涉及连续条件时,就用一维数组,比较i-1与i;有动态规划和贪心两种解法,基本思想一样,当前面和为负(前面的和+nums[i]<nums[i])就舍弃,才能避免拖累下一个数;一维dp数组,dp[i]代表到i为止的连续子序列的最大和;最大和可能在遍历的中间位置,记得随时更新记录)
点击查看代码
class Solution(object):
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# 动态规划解法
# dp[i]代表nums以i为结尾时的连续子数组的最大和
dp = [[0] for _ in range(len(nums))]
# 初始化
dp[0] = nums[0]
# 更新最大和
result = nums[0]
# 开始遍历
for i in range(1, len(nums)):
# 若前几个数的和为整数,那现在的和就加上nums[i];若和为负数就舍弃,只保留nums[i]
dp[i] = max(dp[i-1]+nums[i], nums[i])
result = max(dp[i], result)
return result
# # 解法一:贪心算法吗?怎么不做记录
# if not nums:
# return 0
# dp = [nums[0]]
# res=dp[0]
# for i in range(1, len(nums)):
# dp.append(max(dp[i-1]+nums[i], nums[i]))
# if dp[-1]>res:
# res=dp[-1]
# return res
392.判断子序列(这道题也与最大公共子序列解法一致,具体思路:当两者的最大公共子序列等于前者长度时,说明前者是后者的子序列)
点击查看代码
class Solution(object):
def isSubsequence(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
# 此题解法基于最长公共子序列,如果两者的最长公共子序列的长度正好等于s的长度,那就说明s就是t的子序列
# dp[i][j]代表字符串s的前i-1段和字符串t的前j-1段的最长公共子序列长度,这里用i-1,j-1是为了后面初始化
# 构建二维dp数组
dp = [[0]*(len(t)+1) for _ in range(len(s)+1)]
# 初始化
# 就是第一行和第一列的值都能为零,因为比如dp[0][j]是s的前-1段和t的前j-1段,-1段肯定不存在所以两者公共为0;
# 但是如果前面dp[i][j]设置为前i段和前j段,这里第一行第一列就可能非零了,那很麻烦的。
# 开始遍历
for i in range(1, len(s)+1):
for j in range(1, len(t)+1):
# 由于dp[i-1][j-1]是到i-2和到j-2的公共子序列长度,那如果i-1和j-1处正好相等,那公共子序列长度就再加1
if s[i-1] == t[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = dp[i][j-1]
if dp[len(s)][len(t)] == len(s): # 如果公共子序列长度等于s字符串长度,说明s是t的子序列
return True
else:
return False
PS:今天还是子序列问题,比昨天听的更明白了。
下小雨就像吃点热乎的,今天吃了好吃的排骨米线,辣辣的火鸡面、芝士牛肉石锅、章鱼小丸子,很满足,很撑
2024.11.11 19:48左右 樊某驾车闯入珠海市体育中心,造成35人死亡、43人受伤。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?