學習資料: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人受傷。