Number of Paths with Max Score - Two Approaches - DP, Recursion w/ Memoization [JS]

Description 

Solution 1: DP - Tabulation

Keep track of the max score and number of paths.
Start from the bottom right corner and traverse the three possible paths from each position: right, bottom right, bottom

If the score is bigger than the current max score, update it to the new score and number of paths from that path.
If the score is equal to the current max score, add to the number of paths.

Things to keep in mind:

  • There is no path for 'X'.
  • Only calculate the score for the current square if it's a number (not 'S' or 'E').

Time Complexity: O(n^2) 246ms
Space Complexity: O(n^2) 61.8MB

var pathsWithMaxScore = function(board) {
  let n = board.length, dp = Array(n + 1).fill(0).map(() => Array(n + 1).fill(0).map(() => [-Infinity, 0]));
  let mod = 10 ** 9 + 7;
  dp[n - 1][n - 1] = [0, 1]; // [max score, number of paths]
  
  for (let i = n - 1; i >= 0; i--) {
    for (let j = n - 1; j >= 0; j--) {
      if (board[i][j] === 'X' || board[i][j] === 'S') continue;
      
      let paths = [dp[i][j + 1], dp[i + 1][j + 1], dp[i + 1][j]];
      for (let [maxScore, numPaths] of paths) {
        if (dp[i][j][0] < maxScore) {
          dp[i][j] = [maxScore, numPaths];
        } else if (dp[i][j][0] === maxScore) {
          dp[i][j][1] = (dp[i][j][1] + numPaths) % mod;
        }
      }
      let score = board[i][j] === 'E' ? 0 : Number(board[i][j]);
      dp[i][j][0] += score;
    }
  }
  return dp[0][0][1] === 0 ? [0, 0] : dp[0][0];
};

Solution 2: DP - Recursion w/ Memoization

The same idea as solution 1, but a different approach using recursion and memoization.

Time Complexity: O(n^2) 167ms
Space Complexity: O(n^2) 59.4MB

var pathsWithMaxScore = function(board) {
  let n = board.length, memo = Array(n).fill(0).map(() => Array(n).fill(0).map(() => null));
  let mod = 10 ** 9 + 7;
  let res = dp(n - 1, n - 1);
  return res[1] === 0 ? [0, 0] : res;
  
  function dp(i, j) {
    if (i < 0 || j < 0 || board[i][j] === 'X') return [-Infinity, 0];
    if (i === 0 && j === 0) return [0, 1];
    if (memo[i][j] !== null) return memo[i][j];
    
    let ans = [-Infinity, 0];
    let paths = [dp(i, j - 1), dp(i - 1, j - 1), dp(i - 1, j)];
    for (let [maxScore, numPaths] of paths) {
      if (maxScore > ans[0]) {
        ans = [maxScore, numPaths];
      } else if (maxScore === ans[0]) {
        ans[1] = (ans[1] + numPaths) % mod;
      }
    }
    if (ans[0] !== -Infinity && board[i][j] !== 'S') ans[0] += Number(board[i][j]);
    return memo[i][j] = ans;
  }
};

javascript

Comments

Popular posts from this blog

Maximum Value of an Ordered Triplet II - Two Solutions [JS]

Maximum Sum of Distinct Subarrays With Length K - Sliding Window w/ Two Pointers & Set [JS]

Sum of Prefix Scores of Strings - Trie [JS]

Maximum Count of Positive Integer and Negative Integer - Binary Search [JS]

Count Subarrays With Median K - Count Left & Right Balance [JS]