416. 分割等和子集

Problem: 416. 分割等和子集

Reference

代码随想录 (programmercarl.com)

思路

一个典型的01背包问题。

这里我们使用一维背包,使用一维背包要注意:

  1. 先遍历物品在遍历背包
  2. 遍历背包需要倒序遍历

dp数组含义:大小为j的子集能装的数之和为dp【j】。

递推公式:dp【j】 = max(dp【j】,dp【j - nums【i】 】+ nums【i】);

初始化:dp【0】 = 0;

遍历顺序:上面提到了。

能装得下是大于等于if(j >= nums[i])
不是大于 if(j > nums[i])
不要漏了😓

复杂度

时间复杂度:

添加时间复杂度, 示例: $O(n)$

空间复杂度:

添加空间复杂度, 示例: $O(n)$

Code

[]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {

public:

    bool canPartition(vector<int>& nums) {

        int sum = 0;

        for(int item : nums) {

            sum += item;

        }

        if(sum % 2 == 1) return false;

        int target = sum / 2;

        vector<int> dp(target + 1);

        for(int i = 0; i < nums.size(); i++) {

            for(int j = target; j >= 0; j--) {

                if(j >= nums[i]) {

                    dp[j] = std::max(dp[j],dp[j - nums[i]] + nums[i]);

                }

            }

        }

        return dp[target] == target;

    }

};