leetcode 416 分割等和子集

题目

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

示例

输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

解析

首先这道题是用动态规划的背包问题思路解,虽然我并没有看出了为什么是一个01背包问题。。。
关于01背包的二维数组和一维数组解法,可以看如下链接:
二维数组法
一维数组法
理解下题意,是这个数组的和,可以分割成两个一毛一样的和就是可以的;然后前置的工作准备就是算出来这个数组和除以2得到目标值target(注意理解下这个target代表什么,目前看来有两层含义,第一是最后要比较的目标值,第二是背包的容量)
复习下动态规划五部曲:
1.确定dp数组以及下标的含义
本题中每一个元素的数值既是重量,也是价值;
dp[j]表示背包所能装的总重量是j,放进物品后,背包最大重量为dp[j]
2.确定递推公式
同样,物品i的重量是nums[i],其价值也是nums[i]
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
3.初始化
默认都是0
4.遍历顺序
如果使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环放在内层,且内层for循环倒序遍历(理解不了就背下来把)

func canPartition(nums []int) bool {
    // 先求出来这个数组的总和,然后除以2用于算出target
    sum := 0
    for _, num := range nums {
        sum += num
    }
    if sum % 2 == 1 {
        return false
    }
    target := sum / 2
    dp := make([]int, 20001)
    for i := 0; i < len(nums); i++ {
        for j := target; j >= nums[i]; j-- { // j的容量要大于nums[i]的重量,不然这个物品都装不进去,就没有遍历的必要了
            dp[j] = max(dp[j], dp[j-nums[i]] + nums[i])
        }
    }
    return dp[target] == target
}
func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

你可能感兴趣的:(#,leetcode动态规划系列,leetcode,算法,动态规划)