全部元素相加得到和,如果为奇数,必然无法满足调节,如果为偶数,那么目标子集和已经确定(全部元素和的一半),只要令一个子集的和满足目标,那么可以直接返回 true。所以原题就可以转变为计算nums中的数字能否组成 targetSum。
对于这种问题,首先可以遍历全部的子集和,但可能会造成较大的时间复杂度,出现超出运行时间的错误。由此想到了动态规划(自信一点,想到了就想下去,不要老想着看答案!!),构建 dp []bool 数组,其中dp[i]表示nums中是否存在子数组满足其和==i,最后返回dp[targetSum]即可。可以构建其状态转移方程如下:
dp[i]=dp[i] || (dp[i-num[j]] && num[j])
注意:在构建dp时,因为用下标i表示可以组成的和,所以数组长度应该设置为targetSum+1,同时将dp[0]设置为true
GO
func canPartition(nums []int) bool {
var sum, targetSum int=0, 0
var dp []bool
for _, v:=range nums{ sum+=v }
if sum%2!=0 { return false }
targetSum=sum/2
dp=make([]bool, targetSum+1)
dp[0]=true
for _, v:=range nums{
for i:=targetSum; i>=v; i--{
dp[i]=dp[i] || dp[i-v]
}
}
return dp[targetSum]
}