LeetCode 题解(Week 12):375. Guess Number Higher or Lower II

来源:互联网 发布:安多数据库工程师招聘 编辑:程序博客网 时间:2024/05/18 14:25

原题目:

We are playing the Guess Game. The game is as follows:

I pick a number from 1 to n. You have to guess which number I picked.

Every time you guess wrong, I’ll tell you whether the number I picked is higher or lower.

However, when you guess a particular number x, and you guess wrong, you pay $x. You win the game when you guess the number I picked.

Example:

n = 10, I pick 8.

First round: You guess 5, I tell you that it’s higher. You pay 5.
Second round: You guess 7, I tell you that it’s higher. You pay 7.
Third round: You guess 9, I tell you that it’s lower. You pay 9.

Game over. 8 is the number I picked.

You end up paying 5 + 7 + 9 = 21. Given a particular n ≥ 1, find out how much money you need to have to guarantee a win.

中文大意

有一个猜数字的游戏,给定一个范围n,去猜一个[1,n]的目标数字,每当你猜一个数字i,游戏会返回你猜的数字i比n大还是比n小,并且要罚i这么多的钱,游戏直到你猜对数字才会停止(猜对的话不需要罚钱)。问:如果我要保证赢的话,最少需要罚多少钱?

题解

class Solution {public:    int getMoneyAmount(int n) {        vector<vector<int> > dp(n+1,vector<int>(n+1,0));        for(int l = 1; l <= n;l++)        {            for(int i = 1; i <= n-l ;i++)            {                if(l == 1)  dp[i][i+l] = i;                else if(l == 2)  dp[i][i+l] = i+1;                else                {                    int mincost = min(i+dp[i+1][i+l],i+l+dp[i][i+l-1]);                    for(int j = i+1; j < i+l ;j++)                        mincost = min(mincost,j+max(dp[i][j-1],dp[j+1][i+l]));                    dp[i][i+l] = mincost;                }            }        }        return dp[1][n];    }};

解析:

这道题仍然是用动态规划来解决。定义f[i][j]为[i,j]之间要保证猜中所花费的最少钱,状态转移方程为:f[i][j] = min{k + max{f[i][k-1] , f[k+1][j]} }
直观来讲,就是如果要求[i,j]之间保证能猜中的最少钱,那么问题可以分解为:

  • 猜k但是不中(因为要求至少),所以f[i][j]要加上k
  • 这个时候,目标数字有可能大于k也有可能小于k,这个时候,f[i][j]需要加上f[i][k-1],f[k+1][j]的最大值(因为要保证够钱能猜中)

有了状态转移方程以后,还有一个关键是转移的方向(或者说是迭代的方向),由于状态之间的依赖关系:

  • 例如f[1][3],即(f[1][1+2])需要依赖f[1][1],f[1][2],f[2][2],f[2][3],即f[1][1+0],f[1][1+1],f[2][2+0],f[2][2+1]
  • 定义跨度为j-i的值,意味着,要从跨度入手来进行遍历:要先计算f[i][i+0],然后再算f[i][i+1]……

根据这种思路,算出算法的空间复杂度为O(n^2),时间复杂度为O(n^3)

阅读全文
0 0
原创粉丝点击