Skip to content

Commit 0fcf72b

Browse files
committed
Implement ones-and-zeroes
name: ones-and-zeroes url: https://leetcode.com/problems/ones-and-zeroes difficulty: 2 time: 164 ms time-rank: 86.66 % time-complexity: O((m + n)N) space: 102.5 MB space-rank: 16.76 % space-complexity: O(N*m*n) Fixes #306 This is a 2-D 0-1 Knapsack problem Signed-off-by: Christopher Friedt <[email protected]>
1 parent c935eb5 commit 0fcf72b

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

ones-and-zeroes-test.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2021, Christopher Friedt
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*/
6+
7+
#include <gtest/gtest.h>
8+
9+
#include "ones-and-zeroes.cpp"
10+
11+
using namespace std;
12+
13+
TEST(OnesAndZeros, 10_0001_111001_1_0__5__3) {
14+
vector<string> strs = {"10", "0001", "111001", "1", "0"};
15+
int m = 5;
16+
int n = 3;
17+
EXPECT_EQ(4, Solution().findMaxForm(strs, m, n));
18+
}
19+
20+
TEST(OnesAndZeros, 10_0_1__1__1) {
21+
vector<string> strs = {"10", "0", "1"};
22+
int m = 1;
23+
int n = 1;
24+
EXPECT_EQ(2, Solution().findMaxForm(strs, m, n));
25+
}
26+
27+
TEST(OnesAndZeros, 10_0001_111001_1_0__4__3) {
28+
vector<string> strs = {"10", "0001", "111001", "1", "0"};
29+
int m = 4;
30+
int n = 3;
31+
EXPECT_EQ(3, Solution().findMaxForm(strs, m, n));
32+
}

ones-and-zeroes.cpp

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright (c) 2021, Christopher Friedt
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*/
6+
7+
// clang-format off
8+
// name: ones-and-zeros
9+
// url: https://leetcode.com/problems/ones-and-zeroes
10+
// difficulty: 2
11+
// clang-format on
12+
13+
#include <algorithm>
14+
#include <vector>
15+
16+
using namespace std;
17+
18+
class Solution {
19+
public:
20+
// this is a 2D 1-0 Knapsack problem where
21+
// each item is either included or not included
22+
// in the optimal subset and there are 2 different weights
23+
int findMaxForm(vector<string> &strs, int m, int n) {
24+
int N = strs.size();
25+
26+
// create the weight vectors
27+
w0 = vector<int>(N);
28+
w1 = vector<int>(N);
29+
for (int i = 0; i < N; ++i) {
30+
w0[i] = count(strs[i].begin(), strs[i].end(), '0');
31+
w1[i] = strs[i].size() - w0[i];
32+
}
33+
34+
// create the values vectors
35+
// this is mainly for "muscle memory" - with the
36+
// 0-1 Knapsack problem, elements can still have
37+
// different weights.
38+
val = vector<int>(N, 1);
39+
40+
// create a DP area
41+
dp = vector<vector<vector<int>>>(
42+
N + 1, vector<vector<int>>(m + 1, vector<int>(n + 1, -1)));
43+
44+
// after we have counted 0's and 1's in strs, it is actually not needed
45+
// anymore
46+
return KS(N, m, n);
47+
}
48+
49+
protected:
50+
// "weight" in 0's of strs[i]
51+
vector<int> w0;
52+
// "weight" in 1's of strs[i]
53+
vector<int> w1;
54+
// values of each item
55+
vector<int> val;
56+
57+
// memoization area for Dynamic Programming solution
58+
vector<vector<vector<int>>> dp;
59+
60+
int KS(int i, int m, int n) {
61+
62+
// cout << "looking up dp[" << i << "][" << m << "][" << n << "]" << endl;
63+
auto &result = dp[i][m][n];
64+
if (result != -1) {
65+
return result;
66+
}
67+
68+
if (i == 0) {
69+
result = 0;
70+
return 0;
71+
}
72+
73+
if (m == 0 && n == 0) {
74+
result = 0;
75+
return 0;
76+
}
77+
78+
if (w0[i - 1] > m || w1[i - 1] > n) {
79+
result = KS(i - 1, m, n);
80+
return result;
81+
}
82+
83+
auto t1 = KS(i - 1, m, n);
84+
auto t2 = val[i - 1] + KS(i - 1, m - w0[i - 1], n - w1[i - 1]);
85+
86+
result = max(t1, t2);
87+
return result;
88+
}
89+
};

0 commit comments

Comments
 (0)