LeetCode Solutions

375. Guess Number Higher or Lower II

Time: $O(n^3)$

Space: $O(n^2)$

			

class Solution {
 public:
  int getMoneyAmount(int n) {
    // dp[i][j] := min money you need to guarantee a win of picking i..j
    dp.resize(n + 1, vector<int>(n + 1, INT_MAX));
    return getMoneyAmount(1, n);
  }

 private:
  vector<vector<int>> dp;

  int getMoneyAmount(int i, int j) {
    if (i >= j)
      return 0;
    if (dp[i][j] != INT_MAX)
      return dp[i][j];

    for (int k = i; k <= j; ++k)
      dp[i][j] =
          min(dp[i][j],
              max(getMoneyAmount(i, k - 1), getMoneyAmount(k + 1, j)) + k);

    return dp[i][j];
  }
};
			

class Solution {
  public int getMoneyAmount(int n) {
    // dp[i][j] := min money you need to guarantee a win of picking i..j
    dp = new int[n + 1][n + 1];
    Arrays.stream(dp).forEach(A -> Arrays.fill(A, Integer.MAX_VALUE));
    return getMoneyAmount(1, n);
  }

  private int[][] dp;

  private int getMoneyAmount(int i, int j) {
    if (i >= j)
      return 0;
    if (dp[i][j] != Integer.MAX_VALUE)
      return dp[i][j];

    for (int k = i; k <= j; ++k)
      dp[i][j] = Math.min(
          dp[i][j],
          Math.max(getMoneyAmount(i, k - 1), getMoneyAmount(k + 1, j)) + k);

    return dp[i][j];
  }
}
			

class Solution:
  def getMoneyAmount(self, n: int) -> int:
    # Dp(i, j) := min money you need to guarantee a win of picking i..j
    @functools.lru_cache(None)
    def dp(i: int, j: int) -> int:
      if i >= j:
        return 0

      ans = math.inf

      for k in range(i, j + 1):
        ans = min(ans, max(dp(i, k - 1), dp(k + 1, j)) + k)

      return ans

    return dp(1, n)