leetcode算法题--猜数字大小 II★★

原题链接:https://leetcode-cn.com/problems/guess-number-higher-or-lower-ii/

这题难点在于不能直接使用二分法,举个例子:如果n=5,则1、2、3、4、5,那么先选4,再选2,和为6是最小的,而不是传统二分法的先选3,再选4,和为7。并且这题求的是最好的最坏,也就是min(max())

1、递归+二分法(超时)

int getMoneyAmount(int n) {
     return func(1,n);
 }

 int func(int low,int high){
     if(low>=high) return 0;
     int cost=INT_MAX;
     for(int i=low;i<=high;i++){
         cost=min(cost,i+max(func(low,i-1),func(i+1,high)));//如果选了i的花费
     }
     return cost;
 }

2、递归+二分法优化(超时)

先找最坏情况,因为右边比较大,所以只要每次选择右边代价更高。

int getMoneyAmount(int n) {
     return func(1,n);
 }

 int func(int low,int high){
     if(low>=high) return 0;
     int cost=INT_MAX;
     for(int i=(low+high)/2;i<=high;i++){
         cost=min(cost,i+max(func(low,i-1),func(i+1,high)));
     }
     return cost;
 }

3、动态规划

还是得动态规划

dp[i][j] 代表在(i,j)中最坏情况的最小开销

状态转移

//i<=j<=i+len,每次选择j的最坏代价,并且从中取最小值
dp[i][i+len]=min(j+max(dp[i][j-1],dp[j+1][i+len])

所以是三层循环

int getMoneyAmount(int n) {
    vector<vector<int>> dp(n+1,vector<int>(n+1,0));
    for(int len=1;len<n;len++){
        for(int i=1;i<=n-len;i++){
            int count=INT_MAX;
            for(int j=i;j<i+len;j++){
                count=min(count,j+max(dp[i][j-1],dp[j+1][i+len]));
            }
            dp[i][i+len]=count;
        }
    }
    return dp[1][n];
}

如图,帮助理解
在这里插入图片描述
如(1,3)区间取2是最小结果;(1,4)区间取3、1,3+1=4是最小结果;(1,5)区间取4、2,4+2=6是最小结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值