[关闭]
@iStarLee 2018-10-04T17:38:19.000000Z 字数 2418 阅读 300

[LeetCode] Guess Number Higher or Lower II 猜数字大小之二

robotics-algorithm


参考文章链接

1 我的解决思路和问题描述

一个数字为,在中任意选一个数字作为,可以一直猜测下去,直到猜对。如果用 表示该次使用的猜测数字,如果猜错,则猜错的代价

所以对于 中的其中一个 ,我们如果要猜对的话,那么可能需要猜测很多次,假设我们采用的某种猜测策略需要猜测次,每次猜的数字为。那么为了猜对这个,我们的次猜测错误代价总和表示为

考虑一般情况,在区间中,如果我们使用类似分治法的思想,在区间中任取作为猜测值,那么这个区间内的某一个的代价包括三个部分,的左区间和的右区间的代价和,表示为

也就是针对每一次猜测分割用一个局部最大值(local_max)加上表示能够覆盖本次猜测的所有可能消耗的代价。

但是区间中包括了 的可能,所以我们需要遍历这种可能,分别求出对应的代价,表示为

要注意,在区间上计算代价时有两种可能,第一次取作为猜测的分割点

现在还需要解决最后一个问题,如何保证我们前面的是知道的?

需要两点保证
(1)总区间,采用如下的遍历方式,

  1. for (int i = 2; i <= n; ++i)
  2. {
  3. for (int j = i-1; j >=1 ; --j)
  4. {
  5. }
  6. }

(2) 相差为1的区间代价计算方式
前面提到的,如果,那么直接求出区间代价为
如上两点保证后面用到的每一个区间代价,都是经过前面计算的,也即是动态规划思想,利用前面计算的结果来计算当下的问题。

根据理解修改的网上的demo如下:

  1. #include <iostream>
  2. #include <climits>
  3. #include <vector>
  4. using namespace std;
  5. //采用动态规划的思想
  6. int GuessNumWithMinCost(int n)
  7. {
  8. vector<vector<int>> min_cost(n+1,vector<int>(n+1,0));//方便从1开始访问下标
  9. // 1 ... j ... i ... n
  10. for (int i = 2; i <= n; ++i)
  11. {
  12. for (int j = i-1; j >=1 ; --j)// 先求[j,i]区间内的cost
  13. {
  14. int global_min = INT_MAX;//global_min使用一个较大的数初始化(eg: INT_MAX)
  15. for (int k = j+1; k <= i-1; ++k)////遍历区间[j,i], j+1<=k<=i-1,此处情况为i-j>=2
  16. {
  17. int local_max = k + max(min_cost[j][k-1], min_cost[k+1][i]);//local_max就是考虑局部最坏情况
  18. global_min = min(global_min, local_max);//global_min 就是考虑所有最坏情况后找出损失最小的情况
  19. }
  20. if(i-j>=2)
  21. min_cost[j][i] = global_min;
  22. else//i-j=1时
  23. min_cost[j][i] = j;
  24. }
  25. }
  26. // print min_cost matrix
  27. cout<<"min cost matrix is: \n";
  28. for (int i = 2; i <= n; ++i)
  29. {
  30. for (int j = 1; j <i ; ++j)
  31. {
  32. cout<<min_cost[j][i]<<" ";
  33. }
  34. cout<<endl;
  35. }
  36. return min_cost[1][n];
  37. }
  38. int main(int argc, char const *argv[])
  39. {
  40. int n;
  41. cout<<"please input n: ";
  42. cin>>n;
  43. cout<<"The Min Cost("<<n<<") is: "<<GuessNumWithMinCost(n)<<endl;
  44. return 0;
  45. }

2 网络解题思路

我们想,如果只有一个数字,那么我们不用猜,cost为0。如果有两个数字,比如1和2,我们猜1,即使不对,我们cost也比猜2要低。如果有三个数字1,2,3,那么我们就先猜2,根据对方的反馈,就可以确定正确的数字,所以我们的cost最低为2。如果有四个数字1,2,3,4,那么情况就有点复杂了,那么我们的策略是用k来遍历所有的数字,然后再根据k分成的左右两个区间,取其中的较大cost加上k。

当k为1时,左区间为空,所以cost为0,而右区间2,3,4,根据之前的分析应该取3,所以整个cost就是1+3=4。
当k为2时,左区间为1,cost为0,右区间为3,4,cost为3,整个cost就是2+3=5。
当k为3时,左区间为1,2,cost为1,右区间为4,cost为0,整个cost就是3+1=4。
当k为4时,左区间1,2,3,cost为2,右区间为空,cost为0,整个cost就是4+2=6。
综上k的所有情况,此时我们应该取整体cost最小的,即4,为最后的答案,这就是极小化极大算法。

有两个策略

考虑第一个。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注