返回

[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 最坏情况下需要付出的成本。在对于一个给定范围内,我们可以枚举其中所有的位置进行猜测并对其进行更新,更新的逻辑是:

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

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

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

#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

Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy