Dynamic Programming: 0/1 Knapsack, LCS & LIS
“Overlapping subproblems, 0/1 Knapsack pseudo-polynomial complexity, LCS table reconstruction, and LIS in O(n log n).”
1.The Dynamic Programming Paradigm & Memoization
§ 3.1.Dynamic programming is applicable when a problem has two key ingredients:
1. Optimal Substructure: An optimal solution to the problem contains within it optimal solutions to subproblems.
2. Overlapping Subproblems: A recursive algorithm visits the same subproblems repeatedly rather than generating new subproblems.
Top-Down (Memoization) vs Bottom-Up (Tabulation):
- Top-Down: Write natural recursive formulation, store computed results in hash table or array.
- Bottom-Up: Identify topological ordering of subproblem dependencies and fill an iterative DP table from base cases up.
2.0/1 Knapsack, LCS and Patience Sorting for LIS
§ 3.2.0/1 Knapsack Recurrence:
DP[i][w] = DP[i-1][w] (if wt[i] > w), and max(DP[i-1][w], val[i] + DP[i-1][w - wt[i]]) (if wt[i] <= w).
Time complexity is O(n * W). This is pseudo-polynomial because the input length of capacity W is k = lceil log_2 W rceil bits. Thus W = 2^k, meaning the running time is exponential in the input representation size.
Longest Increasing Subsequence (LIS) in O(n log n):
Maintain an array tails where tails[len] stores the smallest tail of all increasing subsequences of length len + 1 found so far.
For each element x in A:
- Binary search for the first element in tails >= x.
- If found, replace it with x (maintaining smaller tail for that length).
- If x is larger than all elements in tails, append x to tails.
The length of tails at the end is the length of the LIS.
3. Worked Problem: LCS Matrix Table & String Reconstruction
When backtracking in the LCS table, if c[i-1][j] == c[i][j-1], both directions lead to valid optimal LCS strings of equal length.
Problem: Given strings X = 'BDCABA' (length 6) and Y = 'ABCBDAB' (length 7), compute the length of their Longest Common Subsequence and reconstruct one LCS string.
Step 1: Construct (6+1) x (7+1) matrix DP[i][j]:
Rows: X = [-, B, D, C, A, B, A]
Cols: Y = [-, A, B, C, B, D, A, B]
Step 2: Fill rows using recurrence:
Row 1 (B): [0, 0, 1, 1, 1, 1, 1, 1]
Row 2 (D): [0, 0, 1, 1, 1, 2, 2, 2]
Row 3 (C): [0, 0, 1, 2, 2, 2, 2, 2]
Row 4 (A): [0, 1, 1, 2, 2, 2, 3, 3]
Row 5 (B): [0, 1, 2, 2, 3, 3, 3, 4]
Row 6 (A): [0, 1, 2, 2, 3, 3, 4, 4]
Step 3: LCS length:
DP[6][7] = 4.
Step 4: Backtrack from (6, 7):
- At (6, 7), X[6]='A' != Y[7]='B'. DP[5][7]=4, DP[6][6]=4. Move up to (5, 7).
- At (5, 7), X[5]='B' == Y[7]='B'. Match! Pick 'B', move to (4, 6).
- At (4, 6), X[4]='A' == Y[6]='A'. Match! Pick 'A', move to (3, 5).
- At (3, 5), X[3]='C' != Y[5]='D'. DP[2][5]=2, DP[3][4]=2. Move to (3, 3) through (3, 4).
- At (3, 3), X[3]='C' == Y[3]='C'. Match! Pick 'C', move to (2, 2).
- At (2, 2), X[2]='D' != Y[2]='B'. Move up to (1, 2).
- At (1, 2), X[1]='B' == Y[2]='B'. Match! Pick 'B', move to (0, 1).
Reconstructed string (reversed): 'BCAB' (length 4). Other valid LCS is 'BDAB'.
Primary Academic References & Exam Sources
Every concept in Notes From a B.Tech Brain is synthesized from authoritative academic texts, seminal peer-reviewed research, verified exam archives, and renowned university lectures.
Curated for clarity, rigorous numerical solving, and semester excellence:
Best visual explanations of algorithm design and complexity analysis.
Exam-focused with GATE PYQ numericals on every major algorithm.