My Learning Blog

Dynamic program solving template - 2/12/2024

Using five steps to get it

This approach (Bottom-Up Approach (Tabulation)) typically involves filling up a DP table based on the dependencies of subproblems, starting from the simplest subproblem(s) and iteratively solving for more complex ones until the final problem is solved. This method iterates over the problem space to build the solutions of subproblems from the ground up.

Bottom-Up (Tabulation) is iterative and can be more efficient in terms of memory usage, as it doesn’t involve the call stack overhead. It’s typically faster due to the sequential access pattern and can be easier to optimize for space.

General Tips for Dynamic Programming:

Step 1: Define the DP Array

Decide the dimensions of the DP array based on the number of state variables. Make sure you know the meanning of dp[i] or dp[i][j].The state should contain all the information necessary to make future decisions.

Step 2: Determine the Recurrence Relation

State Transition: Formulate how to transition from one state to another, effectively defining the recurrence relation.

For climbing stairs,given you can climb 1 or 2 steps at a time, the number of ways to reach the current step is the sum of the ways to reach the two previous steps. This gives us the recurrence relation:

dp[i] = dp[i - 1] + dp[i -2]

Step 3: Initialize the DP Array

The base cases are: dp[1] = 1, since there is only one way to reach the first stair. dp[2] = 2

Step 4: Determine the Iteration Order

Iterative Order: For the bottom-up approach, determine the order of filling the DP table to ensure dependencies are resolved correctly.

Since the current state depends on the two previous states, we start from the smallest index (after initializing the base cases) and move upwards to n.

Step 5: Identify Optimization Opportunities

Consider if space or time complexity can be improved, such as by using a rolling array to reduce space complexity.

JavaScript Template for DP:

function solveTabulation(problemParams) {
  // Step 1:Define the DP Array
  const dp = new Array(n + 1).fill(initialValue); // Adjust size and initial value as needed

  // Step 3:Initialize the DP Array
  dp[baseCaseIndex] = baseCaseValue;

  // Step 4:Determine the Iteration Order
  for (let i = startingIndex; i <= n; i++) {
    // Step 2:Apply the Recurrence Relation
    dp[i] = dp[i - 1] + dp[i - 2];
  }
  // Step 5: Optimization is possible

  //return the final result
  return dp[n];
}