CodeMosa

Master LeetCode Patterns

IntermediateDynamic ProgrammingRead Dynamic Programming Fundamentals →

Knapsack

0/1, unbounded, bounded, and multi-dimensional knapsack patterns

Time: O(nW)
Space: O(W)

What is Knapsack?

#
Definition: Maximize value under capacity constraints by picking/skipping items; iterate capacity in the right direction per variant.

Core Idea

#

Pick or skip items with weight/cost constraints; iterate capacity in proper order to avoid reuse bugs.

When to Use

#

Use for resource allocation with capacity constraints and combinatorial choices.

How Knapsack works

#

0/1 knapsack iterates capacity in reverse; unbounded iterates forward; extend with counts or extra dimensions when bounded/multi-constraint.

  • Capacity limit
  • Pick/skip
  • Values/weights

General Recognition Cues

#
General indicators that this pattern might be applicable
  • Capacity limit
  • Pick/skip
  • Values/weights
#
Curated practice sets for this pattern

Code Templates

#
0/1 knapsack iterates capacity in reverse; unbounded iterates forward; extend with counts or extra dimensions when bounded/multi-constraint.
# Digit DP Template (No consecutive ones up to N)
from functools import lru_cache

def count_no_consec_ones(n):
    s=bin(n)[2:]
    @lru_cache(None)
    def dp(i, tight, prev1):
        if i==len(s): return 1
        up = int(s[i]) if tight else 1
        total=0
        for d in range(up+1):
            if prev1 and d==1: continue
            total+=dp(i+1, tight and d==up, d==1)
        return total
    return dp(0, True, False)

Pattern Variants & Approaches

#
Different methodologies and implementations for this pattern
1

0/1 Knapsack

#

Each item at most once

When to Use This Variant
  • Binary choice
Use Case
Subset value max
Advantages
  • O(nW)
  • 1D optimize
Implementation
def knapsack_01(weights, values, W):
    dp=[0]*(W+1)
    for w,v in zip(weights, values):
        for c in range(W, w-1, -1):
            dp[c]=max(dp[c], dp[c-w]+v)
    return dp[W]
2

Unbounded

#

Unlimited items

When to Use This Variant
  • Complete knapsack
Use Case
Coin change min ways
Advantages
  • Forward iteration of W
Implementation
def unbounded_knapsack(weights, values, W):
    dp=[0]*(W+1)
    for i,(w,v) in enumerate(zip(weights, values)):
        for c in range(w, W+1):
            dp[c]=max(dp[c], dp[c-w]+v)
    return dp[W]
3

Bounded/Multi

#

Limited counts or multi-constraints

When to Use This Variant
  • Counts or extra dims
Use Case
Multi-resource
Advantages
  • General but heavier
Implementation
# Bounded counts via binary splitting
def bounded_knapsack(weights, values, counts, W):
    items=[]
    for w,v,c in zip(weights,values,counts):
        k=1
        while c>0:
            take=min(k,c); items.append((w*take, v*take)); c-=take; k<<=1
    dp=[0]*(W+1)
    for w,v in items:
        for c in range(W, w-1, -1):
            dp[c]=max(dp[c], dp[c-w]+v)
    return dp[W]

Common Pitfalls

#
Watch out for these common mistakes
  • Iterating capacity wrong direction
  • Double counting items
  • Space blow-up

Example Problems

#
Classic LeetCode problems using this pattern

Complexity Analysis

#
Time Complexity
O(nW)

n items by capacity W.

Space Complexity
O(W)

1D rolling array often works.

Ready to test your knowledge?

Test your pattern recognition with interactive questions