动态规划的重点在于两点:
1、问题可分解成子问题。
2、子问题在后续访问过程中有重复访问的问题。==》可以用空间换时间,建立数组来记录每个子问题的答案结果。
示例:最长递增序列问题。
先放一个暴力递归求解的方法
def L(nums,i):
if i == len(nums)-1: #结束条件
return 1
max_len = 1
for j in range(i+1,len(nums)):
if nums[j] > nums[i]:
max_len = max(max_len,L(nums,j)+1)
return max_len
def length_of_LIS(nums):
return max(L(nums,i) for i in range(len(nums)))
nums = [1,5,2,4,3]
print(length_of_LIS(nums))
再放一个dp算法求解的方法
#最长递增序列问题
memo = {} #dp数组记录中间过程数据 记忆化搜索 用空间换时间
def L(nums,i):
#if i == len(nums)-1: #结束条件,递归算法结束条件判断数组是否已经结束
#return 1
if i in memo: # dp算法的结束条件,判断L子问题是否已经
return memo[i]
max_len = 1
for j in range(i+1,len(nums)): #从当前点的后一个数开始遍历寻找子解的最长递增序列
if nums[j] > nums[i]:
max_len = max(max_len,L(nums,j)+1) #分两种情况,加入这个元素和不加这个元素取最大
memo[i] = max_len
return max_len
def length_of_LIS(nums):
return max(L(nums,i) for i in range(len(nums)))
nums = [1,5,2,4,3]
print(length_of_LIS(nums))
比较这两个求解方法可以得出,他俩之间的区别只有子问题的答案记录与否。
回到学这个算法的初衷 – 求解正则化匹配问题。
首先也是递归求解匹配问题
class Solution:
def isMatch(self, s: str, p: str) -> bool:
if(len(p) == 0): #匹配链为空的时候
return len(s) == 0
elif(len(p) == 1): #匹配链还剩余一个字符
return ((len(s)==1) and (self.isequal(s[0],p[0])))
elif(p[1]!='*'): #匹配链后一个字符是否为* *号要进行多情况考虑,.*分情况进行尝试,1、空匹配,2、多匹配
return ((not(len(s)==0)) and (self.isequal(s[0],p[0])) and (self.isMatch(s[1:],p[1:])))
else: #其余情况,单匹配
while(((not(len(s)==0)) and (self.isequal(s[0],p[0])))):
if(self.isMatch(s,p[2:])):
return True
s=s[1:]
return self.isMatch(s,p[2:])
def isequal(self, a, b):
if (a == b):
return True
elif (b == '.'):
return True
else:
return False
s = "aab"
p = "c*a*b*"
result = Solution().isMatch(s,p)
print(result)
dp动态规划算法求解
class Solution:
def isMatch(self, s: str, p: str) -> bool:
#传入两个字符,传回来是否可以匹配
def match(a, b):
return a > 0 and s[a] == p[b] or p[b] == '.'
m, n = len(s), len(p)
#dp数组
dp = [[0]*(n+1) for _ in range(m+1)]
dp[0][0] = 1
#因为匹配链是一直连续下去的 所以这里的按位或是一种传递手段,只有当前面匹配的时候后面才有可能为1
#为什么dp数组要比实际的数组大一个数据,免于考虑数据是否超出范围的问题。
for i in range(m+1):
for j in range(1, n+1):
if p[j-1] == '*':
dp[i][j] |= dp[i][j-2] #按位或
if match(i, j-1):
dp[i][j] |= dp[i-1][j]
else:
if match(i, j):
dp[i][j] |= dp[i-1][j-1]
return True if dp[m][n] else False
s = "aab"
p = "c*a*b*"
result = Solution().isMatch(s,p)
print(result)