Why can’t you solve this problem like this, won’t this get the same runtime O(n*total_sum) but the code is more clean:
def knapsack_weight_only(weights: List[int]) → List[int]:
res = set([0])
for num in weights:
cur_sums = []
for sum_ in res:
if num+sum_ not in res:
cur_sums.append(num+sum_)
res.update(cur_sums)
return list(res)
The solution is so unoptimal, why would you use vectors with total_sum lengths each? Imagine if you have 100 numbers with values about 10M in that case the length of vectors should be about 1B and you need a loop 1B times! The right approach is to use set of sums combinable with 0-i weights and the number of elements of that set would be doubled on each step in worst case so we have time complexity O(2^n) in worst case. Though it even worse for silly vector with total_sum length
In the main function, instead of printing System.out.print(i), it needs to be printing System.out.print(res.get(i))
I changed it and solution is correct now. May just want to change that to show by default.
Love this platform, keep it up
C# output mismatch on equal results and last line in main should join res instead of row
Updated, thanks!
Updated, thanks!
Grad you’re enjoying the platform
Still see an old one.
Hi Vladislav, I meant it’ll be included in the next deployment
@mod memo
is not getting updated in memoized version of generate_sums
function.
Anyone having issues with the tester? the output is not actually whats returned from the code. I tried copying the solution and running the tester, and it failed too.
Why isnt there an option to see the solution in the “Try-it-yourself” portion?
Isn’t this a strictly better solution?
def knapsack_weight_only(weights: List[int]) → List[int]:
dp = set([0])
for weight in weights:
for currentWeight in list(dp):
dp.add(currentWeight + weight)
return list(dp)
Problems with multiple solutions currently do not have one-click solution loading function.
created github issue https://github.com/realAlgoMonster/contrib/issues/66 to cleanup topdown solution - just in case anyone’s top down solution is not working.
JS Bottom-Up solution with space optimization
function knapsackWeightOnly(weights) {
const n = weights.length;
const totalSum = weights.reduce((sum, weight) => sum + weight, 0);
const dp = Array.from(
{ length: 2 },
() => Array(totalSum + 1).fill(false)
);
dp[0][0] = true;
for (let i = 1; i <= n; i++) {
for (let w = 0; w <= totalSum; w++) {
dp[1][w] = dp[1][w] || dp[0][w];
if (w >= weights[i - 1]) {
dp[1][w] = dp[1][w] || dp[0][w - weights[i - 1]];
}
}
for (let w = 0; w <= totalSum; w++) {
dp[0][w] = dp[1][w];
}
}
const result = [];
for (let w = 0; w <= totalSum; w++) {
if (dp[0][w]) result.push(w);
}
return result;
}
For the python bottom up solution:
Line 11: what is the current item’s weight (w[i-1]), and what is the target weight (w), as in why are they called current item and target? I don’t understand what the check does.
Thank you so much.
For the python bottom up solution:
Line 11: what is the current item’s weight (w[i-1]), and what is the target weight (w), as in why are they called current item and target? I don’t understand what the check does.
Thank you so much.
To me, using Set with custom class to record visited node is much easier to understand.
Here is a Java example:
private static class Coordinate{
int x;
int y;
public Coordinate(int xValue, int yValue) {
this.x = xValue;
this.y = yValue;
}
@Override
public int hashCode() {
return x + y;
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
Coordinate coordinate = (Coordinate)obj;
return (coordinate.x == x && coordinate.y == y);
}
}
public static List<Integer> knapsackWeightOnly(List<Integer> weights) {
List<Integer>answer = new ArrayList<>();
Set<Integer>set = new HashSet<>();
Set<Coordinate>visited = new HashSet<>();
answer.add(0);
set.add(0);
dfs(answer, weights, set, visited, 0, 0);
return answer;
}
private static void dfs(List<Integer>answer, List<Integer> weights, Set<Integer>set, Set<Coordinate>visited,
int index, int sum) {
Coordinate coordinate = new Coordinate(index, sum);
if (visited.contains(coordinate)) return;
if (index == weights.size()) {
if (!set.contains(sum)) {
set.add(sum);
answer.add(sum);
}
return;
}
int next = sum + weights.get(index);
dfs(answer, weights, set, visited, index + 1, next);
next = sum;
dfs(answer, weights, set, visited, index + 1, next);
visited.add(coordinate);
}
I simplified the last version of the solution in a way that made it easier for me to understand the approach. Hope you find it useful.
std::vector knapsack_weight_only(std::vector weights) {
int totalSum = accumulate(weights.begin(), weights.end(), 0);
int size = weights.size();
vector<vector> dp(2, vector(totalSum + 1, false));
dp[0][0] = true;
dp[1][0] = true;
for (int i = 1; i <= size; i++) {
for (int w = 0; w <= totalSum; w++) {
if (w - weights[i - 1] >= 0) {
dp[1][w] = dp[1][w] || dp[0][w - weights[i - 1]];
}
}
dp[0] = dp[1];
}
vector<int> ans;
for (int w = 0; w <= totalSum; w++) {
if (dp[1][w]) {
ans.push_back(w);
}
}
return ans;
}