0%

[Leetcode]375. Guess Number Higher or Lower II(C++)

题目描述

题目链接:375. Guess Number Higher or Lower II

We are playing the Guessing Game. The game will work as follows:

  1. I pick a number between 1 and n.
  2. You guess a number.
  3. If you guess the right number, you win the game.
  4. 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.
  5. 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.

例子

例子 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.

例子 2

Input: n = 1
Output: 0
Explanation: There is only one possible number, so you can guess 1 and not have to pay anything.

例子 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

  • 1 <= n <= 200

解题思路

这道题可以看到数据规模不大,我们可以考虑用暴力枚举的方法(相对高的时间复杂度,但不到指数级别)。然后这种求极值的题目可以从动态规划的思路去思考,考虑采用一个二维数组 minAmount,其中 minAmount[left][right] 表示给定范围为 leftright 最坏情况下需要付出的成本。在对于一个给定范围内,我们可以枚举其中所有的位置进行猜测并对其进行更新,更新的逻辑是:

从猜测的位置左右两侧挑选一个更大的值作为最坏情况,加上猜测的值本身作为本次猜测能得到最小的保证赢的成本,并和当前成本进行比较取最小值。

1
2
3
4
minAmount[left][right] = min(minAmount[left][right], \
guess_num + \
max(minAmount[left][guess_num - 1],\
minAmount[guess_num + 1][right]));

具体代码如下:查表过程中需要考虑边界值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <climits>
#include <cmath>
#include <vector>

class Solution {
public:
int getMoneyAmount(int n) {
std::vector<std::vector<int>> minAmount(
n + 1, std::vector<int>(n + 1, INT_MAX));

// if the length of range is 1, we will win at a guess, so no cost
for (int i = 1; i <= n; i++) minAmount[i][i] = 0;

for (int len = 2; len <= n; ++len) {
for (int left = 1; left <= n - len + 1; ++left) {
int right = left + len - 1;
for (int guess = left; guess <= right; ++guess) {
// choose worst scenarios from either left or right side of
// guessing
minAmount[left][right] = std::min(
minAmount[left][right],
guess + std::max(
lookupAmount(minAmount, left, guess - 1),
lookupAmount(minAmount, guess + 1, right)));
}
}
}

return minAmount[1][n];
}

private:
int lookupAmount(const std::vector<std::vector<int>>& minAmount, int l,
int r) {
if (l > r || l < 0 || r >= minAmount.size()) return 0;
return minAmount[l][r];
}
};
  • 时间复杂度: O(n^3)
  • 空间复杂度: O(n^2)

GitHub 代码同步地址: 375.GuessNumberHigherOrLowerIi.cpp

其他题目:
GitHub: Leetcode-C++-Solution
博客: Leetcode-Solutions