动态规划问题特点:
1 求最优解(乘积最大值,最多组合)
2 可分解成若干子问题的最优解(递归)
3 从上到下分析问题,从下到上求解问题
先求基础的子问题最优解——>保存这些最优解到一个数组——>依赖已求的子问题,求解整体最优解
#f(n)=max(f(i)*f(n-i)),0<i<length
fdef cut_rope(length):
if length<2:return 0
if length==2: return 1
if length==3: return 2
counts=[0]*(length+1)#存放子问题的最优解
counts[0]=0
counts[1]=1
counts[2]=2
counts[3]=3
for i in range(4,length+1):
maxnum=0
for j in range(1,i//2+1): #需要取到i/2,所以range里面的时候用地板除,记得加一
temp=counts[j]*counts[i-j]
maxnum=max(maxnum,temp)
counts[i]=maxnum
return counts[length]
#递归问题,f(i)=f(i+1)+g(i,i+1)*f(i+2)
#动态规划,从后向前找
def Print(numbers):
if numbers<0:
print(None)
return find(numbers)
def find(numbers):
numbers=str(numbers)
length=len(numbers)
counts=[0]*length #记录子问题最优解
for i in range(length-1,-1,-1):
count=0
if i==length-1:
count+=1
else:
#通常情况f(i+1)种
count+=counts[i+1]
#判断,若i可以和i+1位组成两位数,且在0——25内,则g=1,增加f(i+1)
#且该判断需在i < length-1的时候(i=length-1时i+2会出界)
num=int(numbers[i])*10+int(numbers[i+1])
if num>=0 and num<=25:
count+=counts[i+2] if i<length-2 else 1
counts[i]=count #从后向前依次更新
return counts[0]
#No.47 礼物的最大值
#递归:f(i,j)=max(f(i-1,j),f(i,j-1))+values[i,j]
#用一个二维数组保存每个位置的最大值,最后返回[row,val]位置的值
def Maxvalue(matrix):
row=len(matrix)
col=len(matrix[0])
Maxvalue=[[0]*col]*row
for i in range(row):
for j in range(col):
up=0 #i=0时
left=0 #j=0时
if i>0:
up=Maxvalue[i-1][j]
if j>0:
left=Maxvalue[i][j-1]
maxnum=max(up,left)+matrix[i][j]
Maxvalue[i][j]=maxnum
return Maxvalue[-1][-1]
a=[[1,1,1],[2,3,1],[2,2,2]]
Maxvalue(a)
# 优化:只用一维数组保存每一行的最大值。f(i,j)不依赖于f(i-1,j-1)
def Maxvalue(matrix):
row=len(matrix)
col=len(matrix[0])
Maxvalue=[0]*col
for i in range (row):
for j in range(col):
up=0
left=0
if i >0:
up=Maxvalue[j]
if j >0:
left=Maxvalue[i-1]
maxnum=max(up,left)+matrix[i][j]
Maxvalue[j]=maxnum
return Maxvalue[-1]
思路:
动态规划:
遍历每一个字符串,计算以当前字符结尾的最长不重复子字符串的长度:并记录
1 若前面没有和当前字符重复的:f(i)=f(i-1)+1
2 前面有和当前重复的: 若重复的字符不在前一个字符串里面:则f(i)=f(i-1)+1;若重复的在前一个字符串里面:则f(i)=d(两个重复的字符的距离)
def Maxlength(string):
string=[str(n) for n in string]
length=len(string)
Maplength=[0]*length #记录以每个字符为结尾的最长不重复字符串长度值
for i in range(length):
if i==0:
curlength=1
else:
j=i-1
Flag=False #记录是否重复,否则 d==i时,不知道是重复还是到首字符
while j>=0:
if string[j]==string[i]:
Flag=True
break
j-=1
d=i-j
if (d==i and not Flag) or d >Maplength[i-1]:
#若不重复或者上一个重复的字符不在前一个连续不重复字符串里
curlength=Maplength[i-1]+1
else:
#若重复,且重复字符在上一个不重复字符串里面
curlength=d
Maplength[i]=curlength
return max(Maplength)
a=Maxlength('arabcacfr')
#Maplength:[1, 2, 2, 3, 4, 3, 2, 3, 4]
# 4
上述方法两次遍历,时间复杂度O(),可以优化,用字典查找重复字符的位置更快
#优化:查找重复时不用遍历,用字典查找
def Maxlength(string):
string=[str(n) for n in string]
length=len(string)
d={}
if length==1:
return 1
curlength=1
maxlength=1
d[string[0]]=0 #用字典记录每个值的位置
for i in range(1,length):
if string[i] not in d:
curlength+=1
else:
dist=i-d[string[i]] 计算距重复字符的距离
if dist>curlength:
curlength+=1
else:
maxlength=max(maxlength,curlength)
curlength=dist
d[string[i]]=i #每次都更新字符最后一次出现的位置
return max(curlength,maxlength) #最后一个curlength没有加入maxlength