Guess Number Higher or Lower II
Problem Description​
We are playing the Guessing Game. The game will work as follows:
I pick a number between 1 and n. You guess a number. If you guess the right number, you win the game. If you guess the wrong number, then I will tell you whether the number I picked is higher or lower, and you will continue guessing. Every time you guess a wrong number x, you will pay x dollars. If you run out of money, you lose the game. Given a particular n, return the minimum amount of money you need to guarantee a win regardless of what number I pick.
Examples:​
Example 1:
Input: n = 10
Output: 16
Explanation: The winning strategy is as follows:
- The range is [1,10]. Guess 7.
- If this is my number, your total is $0. Otherwise, you pay $7.
- If my number is higher, the range is [8,10]. Guess 9.
- If this is my number, your total is $7. Otherwise, you pay $9.
- If my number is higher, it must be 10. Guess 10. Your total is $7 + $9 = $16.
- If my number is lower, it must be 8. Guess 8. Your total is $7 + $9 = $16.
- If my number is lower, the range is [1,6]. Guess 3.
- If this is my number, your total is $7. Otherwise, you pay $3.
- If my number is higher, the range is [4,6]. Guess 5.
- If this is my number, your total is $7 + $3 = $10. Otherwise, you pay $5.
- If my number is higher, it must be 6. Guess 6. Your total is $7 + $3 + $5 = $15.
- If my number is lower, it must be 4. Guess 4. Your total is $7 + $3 + $5 = $15.
- If my number is lower, the range is [1,2]. Guess 1.
- If this is my number, your total is $7 + $3 = $10. Otherwise, you pay $1.
- If my number is higher, it must be 2. Guess 2. Your total is $7 + $3 + $1 = $11.
The worst case in all these scenarios is that you pay $16. Hence, you only need $16 to guarantee a win.
Example 2:
Input: n = 1
Output: 0
Explanation: There is only one possible number, so you can guess 1 and not have to pay anything.
Example 3:
Input: n = 2
Output: 1
Explanation: There are two possible numbers, 1 and 2.
- Guess 1.
- If this is my number, your total is $0. Otherwise, you pay $1.
- If my number is higher, it must be 2. Guess 2. Your total is $1.
The worst case is that you pay $1.
Constraints:​
Algorithm Explanation​
-
Dynamic Programming Table Setup:
- We create a 2D DP array
dp
wheredp[start][end]
represents the minimum amount of money required to guarantee a win if the number is betweenstart
andend
.
- We create a 2D DP array
-
Base Case:
- If
start == end
, no money is needed because we have only one number to guess. Sodp[start][end] = 0
.
- If
-
Filling the DP Table:
- We fill the table for ranges starting from the largest range down to the smallest.
- For each range
[start, end]
, we consider every possible guessi
within that range. - The cost for a guess
i
isi
plus the maximum of the costs of the two resulting subranges[start, i-1]
and[i+1, end]
(since we are guaranteed a win, we must consider the worst-case scenario). - We choose the guess that minimizes this maximum cost.
-
Result:
- The result is stored in
dp[1][n]
which represents the minimum amount of money needed to guarantee a win when guessing a number between 1 andn
.
- The result is stored in
C++ Code​
class Solution {
public:
int getMoneyAmount(int n) {
vector<vector<int>> dp(n + 2, vector<int>(n + 2, 0));
for (int start = n; start >= 1; --start) {
for (int end = start + 1; end <= n; ++end) {
int mini = INT_MAX;
for (int i = start; i <= end; ++i) {
int leftRange = dp[start][i - 1];
int rightRange = dp[i + 1][end];
int cost = i + max(leftRange, rightRange);
mini = min(mini, cost);
}
dp[start][end] = mini;
}
}
return dp[1][n];
}
};
Python Code​
class Solution:
def getMoneyAmount(self, n: int) -> int:
dp = [[0] * (n + 2) for _ in range(n + 2)]
for start in range(n, 0, -1):
for end in range(start + 1, n + 1):
mini = float('inf')
for i in range(start, end + 1):
leftRange = dp[start][i - 1]
rightRange = dp[i + 1][end]
cost = i + max(leftRange, rightRange)
mini = min(mini, cost)
dp[start][end] = mini
return dp[1][n]
Java Code​
class Solution {
public int getMoneyAmount(int n) {
int[][] dp = new int[n + 2][n + 2];
for (int start = n; start >= 1; start--) {
for (int end = start + 1; end <= n; end++) {
int mini = Integer.MAX_VALUE;
for (int i = start; i <= end; i++) {
int leftRange = dp[start][i - 1];
int rightRange = dp[i + 1][end];
int cost = i + Math.max(leftRange, rightRange);
mini = Math.min(mini, cost);
}
dp[start][end] = mini;
}
}
return dp[1][n];
}
}
JavaScript Code​
var getMoneyAmount = function (n) {
const dp = Array.from({ length: n + 2 }, () => Array(n + 2).fill(0));
for (let start = n; start >= 1; start--) {
for (let end = start + 1; end <= n; end++) {
let mini = Infinity;
for (let i = start; i <= end; i++) {
let leftRange = dp[start][i - 1];
let rightRange = dp[i + 1][end];
let cost = i + Math.max(leftRange, rightRange);
mini = Math.min(mini, cost);
}
dp[start][end] = mini;
}
}
return dp[1][n];
};