算法每日一题
Posted Rgylin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法每日一题相关的知识,希望对你有一定的参考价值。
题目链接
题目描述:给你一个 只包含正整数 的 非空 数组
nums
。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
输入:nums = [1,5,11,5] 输出:true 解释:数组可以分割成 [1, 5, 5] 和 [11] 。
法一:
利用回溯算法,找到与nums 总和的一半即可返回
class Solution:
def canPartition(self, nums: List[int]) -> bool:
path=[]
result=[]
def backTo(s,startIndex,used):
if(sum(path)==tar):
result.append(path[:])
if(sum(path)>tar):
return
for i in range(startIndex,len(s)):
if(i>0 and s[i]==s[i-1] and used[i-1]==False):
continue
used[i]=1
path.append(s[i])
backTo(s,i+1,used)
used[i]=0
path.pop()
if(sum(nums)%2!=0):
print('false')
else:
tar=sum(nums)//2
used=len(nums)*[0]
backTo(nums,0,used)
if(result):
return True
else:
return False
但是时间却超时了. 显然对应大数组来说很鸡肋
方法2
利用01背包,将 总和的一半看作是容量,在nums数组中取一半数值即可成功,所以dp表示: 容量为j中取的最大和是多少
满足条件
- 背包容量是sum//2
- 要放入的商品,为nums[i]数值,产生的价值也是nums[i],怎么最大正好装满产生nums//2的子集总和
- 每一个元素不可重新放入
所以写的代码为
def back_01(s,tar,dp):
for i in range(len(s)):
for j in range(tar,nums[i]-1,-1):
dp[j] = max(dp[j],dp[j-nums[i]]+nums[i])
print(dp)
return dp
if __name__ == '__main__':
nums = [1,5,11,5]
if(sum(nums)%2!=0):
pass
else:
target= sum(nums)//2
dp= [0]*(target+1)
print(back_01(nums,target,dp))
最终也是成功通过
以上是关于算法每日一题的主要内容,如果未能解决你的问题,请参考以下文章