Complete-Preparation

πŸŽ‰ One-stop destination for all your technical interview Preparation πŸŽ‰

View the Project on GitHub

0-1 Knapsack Problem

Brute Solution:

Code

/* A Naive recursive implementation of 0-1 Knapsack problem */
int knapSack(int W, int wt[], int val[], int n)
{
    // Base case - If n is 0 or w is 0, then return 0
    if (n == 0 || W == 0)
        return 0;

    // choice diagram code
    // if weight of last item(nth item) is less than or equal to W we can add it else not.
    if (wt[n - 1] <= W)
    {
        // Return the maximum of two cases: (1) nth item included (2) not included
        return max(knapSack(W, wt, val, n - 1), val[n - 1] + knapSack(W - wt[n - 1], wt, val, n - 1));
    }
    else if (wt[n - 1] > W)
    {
        // Don't include the nth item and reduce the input
        return knapSack(W, wt, val, n - 1);
    }
}

Complexity Analysis:


DP APPROACHES

A) Memorization (Top Down)


int dp[1002][1002];
void initialize()
{
    for (int i = 0; i < 1002; i++)
        for (int j = 0; j < 1002; j++)
            dp[i][j] = -1;
}

int knapSackRec(int W, int wt[], int val[], int n)
{
    // Base case - If n is 0 or w is 0, then return 0
    if (n == 0 || W == 0)
        return 0;

    // If this state is previously present we return it.
    if (dp[n][W] != -1)
        return dp[n][W];

    // if weight of last item(nth item) is less than or equal to W we can add it else not.
    if (wt[n - 1] <= W)
    {
        // Return the maximum of two cases: (1) nth item included (2) not included
        return dp[n][W] = max(knapSackRec(W, wt, val, n - 1), val[n - 1] + knapSackRec(W - wt[n - 1], wt, val, n - 1));
    }
    else if (wt[n - 1] > W)
    {
        // Don't include the nth item and reduce the input
        return dp[n][W] = knapSackRec(W, wt, val, n - 1);
    }
}

int knapSack(int W, int wt[], int val[], int n)
{
    initialize();
    return knapSackRec(W, wt, val, n);
}

Complexity Analysis:


B) Tabulation (Bottom Up)

Code


// dp[n+1][W+1] - Global declaration initialize it with 0 , no need for initialization, n = i, W = j
int dp[1002][1002];

int knapSack(int W, int wt[], int val[], int n)
{

    for (int i = 1; i < n + 1; i++)
    {
        for (int j = 1; j < W + 1; j++)
        {
            // if(i==0 || j==0)dp[i][j] = 0; if we start from i=0 and j==0 include this condition.
            if (wt[i - 1] <= j)
            {
                dp[i][j] = max(dp[i - 1][j], val[i - 1] + dp[i - 1][j - wt[i - 1]]);
            }
            else
            {
                dp[i][j] = dp[i - 1][j];
            }
        }
    }
    return dp[n][W];
}

Complexity Analysis:


(C) DP with optimized space complexity

int knapSack(int W, int wt[], int val[], int n)
{
    int dp[W + 1];
    memset(dp, 0, sizeof(dp));

    for (int i = 1; i < n + 1; i++)
    {
        for (int j = W; j >= 0; j--)
        {
            if (wt[i - 1] <= j)
                dp[j] = max(dp[j], dp[j - wt[i - 1]] + val[i - 1]);
        }
    }
    return dp[W];
}

Complexity Analysis:


References