今天是4/17,明天初赛,吧之前leetcode几道动态规划整理一遍
这是一道较有难度的动态规划题,之前刷了几次没写出来,现在从代码的角度做个梳理,
1.明确目标,题目问的是子集的个数,也就是说,最大有多少个数这一类问题,所以再写递归的时候,变量ans求的是个数。
2.围绕ans做思路,既然要求ans,肯定用max函数
class Solution:
def findMaxForm(self, strs,m,n):
def dfs(index,m,n):
if index==len(strs):
return 0
ze=strs[index].count('0');on=strs[index].count('1');ans=0
if ze<=m and on<=n:
ans=1+dfs(index+1,m-ze,n-on)
ans=max(ans,dfs(index+1,m,n))
return ans
return dfs(0,m,n)
3.获取数组索引中的零和一,这里开始因为我的思路不在长度上,我先获取最大字符串长度,然后再找他的个数,这里踩了不少坑,,
我这里看看之前的错误思路
先做两个小测试,拼接字符串和找最大值,到这里一切都正常
然后,写成递归后,return返回了None,说明代码里的cur出问题了,
再做个测试。。
cur=max(cur,dfs(cur+“1”)),这里dfs函数每次遍历都会有一个return cur的值,cur表示某个+"1"拼接字符串,但编译器返回了空。那不而了之
然后,回过头看看之前思路好的代码,ans=1+dfs(index+1,m-ze,n-on)。dfs递归实现了什么? 他的值是多少?
index+1,则在继续遍历,到终止条件index==len(strs)停止,dfs遍历一次,ans的值+1,遍历两次,ans的值+2,所以,单纯的ans=dfs(index+1,m,n),值是没有+的,这用来实现不选某个数组值
ans=max(ans,dfs(index+1,m,n))。取这个元素or接着遍历
这样写,存在很多子重复问题,
只过了将近1/3的数据,我想到用记忆化递归做数组处理,
然后发现 [‘10’,‘0’,‘1’]这种情况时,由于 '10’和(‘0’,‘1’)都满足情况,但不能返回最大个数,不而了之,
后来 看了某佬哥的笔记,加入@lru_cache(None),用缓存优化递归,
在这个基础上,看个简单的题,
明确目标:数组能不能分成左右两侧值相等? 能返回true,不能返回False
,那么,return False or True ,变量res存储的是0或1,,
看了某老哥的写法后,思路是取一半,target==sum/2,如果他是奇数,直接False,如果他是偶数,那可能有机会。
如果处理选or 不选
res=test(sum1+nums[i],i+1) or test(sum1,i+1)
注意这里不选需要前面返回False, 这里的res只能返回布尔型,配合or做选或不选,如果res不为布尔,那or失效
class Solution:
def canPartition(self, nums):
sum=0;arr={}
for i in range(len(nums)):
sum+=nums[i]
if sum%2!=0:
return False
target=sum/2
def test(sum1,index):
if index>=len(nums) or sum1>sum/2:
return False;
if sum1==target:
return True;
for i in range(index,index+2):
# if (sum1,index) in arr:
# return arr[(sum1,index)]
res=test(sum1+nums[i],index+1) or test(sum1,index+1)
# arr[(sum1,i)]=res
#print(arr)
return res
return test(0,0)
递归过了1/3的数据
这里要写for遍历,范围是index,index+2,这个数和后一个数,感觉没啥必要,没有用到max函数,但去掉报错了。。
记忆化递归比较好写这题,一维数组递归就行
数组索引这样,,,比较容易看**,值是布尔,索引是sum1**