-
Notifications
You must be signed in to change notification settings - Fork 118
/
Copy path416. Partition Equal Subset Sum.cpp
135 lines (122 loc) · 4.7 KB
/
416. Partition Equal Subset Sum.cpp
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//0/1 Knapsack Problem
//https://leetcode.com/problems/partition-equal-subset-sum/discuss/90592/01-knapsack-detailed-explanation
//Runtime: 1032 ms, faster than 5.04% of C++ online submissions for Partition Equal Subset Sum.
//Memory Usage: 11 MB, less than 47.06% of C++ online submissions for Partition Equal Subset Sum.
//time: O(NW), space: O(NW)
class Solution {
public:
bool canPartition(vector<int>& nums) {
int n = nums.size(); //number of objects
int capacity = accumulate(nums.begin(), nums.end(), 0);
if((capacity & 1) == 1) return false;
capacity /= 2;
/*
the +1 is not padding, it's meaningful!
i: number of objects in the backpack
j: current weight of backpack
dp[i][j]: whether the state: (i, j) exists or not
our goal is to find out dp[n][capacity]
*/
vector<vector<bool>> dp(n+1, vector<bool>(capacity+1, false));
for(int i = 0; i <= n; i++){
for(int j = 0; j <= capacity; j++){
if(i == 0 && j == 0){
//choose nothing, make up weight = 0
dp[i][j] = true;
continue;
}else if(j == 0){
//make up weight = 0
dp[i][j] = true;
continue;
}else if(i == 0){
//no object to choose, but need to make up weight j > 0
dp[i][j] = false;
continue;
}
/*
not choose this object,
so the weight remains the same(= j)
*/
dp[i][j] = dp[i-1][j];
/*
need to check whether the remaining capacity
still allows us to choose object i:
j >= nums[i] means we still have enough capacity
note that dp[i] corresponds to nums[i-1]!!
(because the i in dp[i] means number of items!)
*/
if(j - nums[i-1] >= 0){
dp[i][j] = dp[i][j] | dp[i-1][j-nums[i-1]];
}
}
}
return dp[n][capacity];
}
};
//optimization, O(N) space
class Solution {
public:
bool canPartition(vector<int>& nums) {
int n = nums.size(); //number of objects
int capacity = accumulate(nums.begin(), nums.end(), 0);
if((capacity & 1) == 1) return false;
capacity /= 2;
/*
the +1 is not padding, it's meaningful!
i: number of objects in the backpack
j: current weight of backpack
dp[i][j]: whether the state: (i, j) exists or not
our goal is to find out dp[n][capacity]
*/
vector<bool> dp(capacity+1, false);
dp[0] = true;
for(int i = 1; i <= n; i++){
for(int j = capacity; j >= 0; j--){
if(j == 0){
dp[j] = false;
}
if(j - nums[i-1] >= 0){
dp[j] = dp[j] | dp[j-nums[i-1]];
}
}
}
return dp[capacity];
}
};
//bitset
//https://leetcode.com/problems/partition-equal-subset-sum/discuss/90590/Simple-C%2B%2B-4-line-solution-using-a-bitset
//Runtime: 12 ms, faster than 90.14% of C++ online submissions for Partition Equal Subset Sum.
//Memory Usage: 9.1 MB, less than 52.94% of C++ online submissions for Partition Equal Subset Sum.
class Solution {
public:
bool canPartition(vector<int>& nums) {
/*
Note:
Each of the array element will not exceed 100.
The array size will not exceed 200.
we want to check if we can make up sum/2 by some elements,
so we don't care anything > sum/2,
and by the Note above,
we can inspect that the max possible sum/2 is 100*200/2 = 10000,
since we still need place for sum equal to 0(the least significant bit),
so totally we need 10001 bits
we initialize bits as 1,
this is saying that we can choose 0 elements to make up 0(x)
this is just for convenience, so that we can use bits |= bits << n;
*/
bitset<10001> bits(1);
int sum = accumulate(nums.begin(), nums.end(), 0);
/*
initially, we can make up 0
1st iter: "bits" is set in 0th and nums[0]th bit
2nd iter: "bits" is set in 0, nums[0], nums[1] and nums[0]+nums[1]th bit
...
*/
for (auto n : nums) bits |= bits << n;
/*
need to check if the sum is even first!
bits[sum >> 1]: whether we can make up sum/2 by nums's subset
*/
return !(sum & 1) && bits[sum >> 1];
}
};