栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

力扣每日一题2021-11-12猜数字大小II

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

力扣每日一题2021-11-12猜数字大小II

猜数字大小II
  • 375.猜数字大小II
    • 题目描述
    • 思路:动态规划
      • Java实现
      • Python实现


375.猜数字大小II 题目描述

猜数字大小II


思路:动态规划

为了将支付的金额最小化,除了需要将每次支付的金额控制在较低值外,还需要在猜数字的过程中缩小所选数字的范围。当猜了数字x且猜错的情况下,会知道x比所选数字大还是小。如果x比所选数字大,应该在比x小的数字中挑选数字猜。如果x比所选数字小,则应该在比x大的数字中挑选数字猜。
用f(i, j)表示在范围[i, j]内确保胜利的最少金额,目标是计算f(1, n)。
假定第一次猜的数字是x并且猜错,则需要支付金额x,当x大于所选数字时,为了确保胜利还需要支付的金额是f(1, x-1),当x小于所选数字时,为了确保胜利还需要支付的金额是f(x+1, n)。为了在任何情况下都能确保胜利,应考虑最坏情况,计算f(1, n)时应取上述两者的最大值:f(1, n) = x + max(f(1, x-1), f(x+1, n))。
为了将确保胜利的金额最小化,需要遍历从1到n的所有可能的x,使得f(1, n)的值最小:
f ( 1 , n ) = m i n 1 < = x < = n ( x + m a x ( f ( 1 , x − 1 ) , f ( x + 1 , n ) ) ) f(1, n) = min_{1<=x<=n}(x+max(f(1, x-1), f(x+1, n))) f(1,n)=min1<=x<=n​(x+max(f(1,x−1),f(x+1,n)))
由于f(1, x-1)和f(x+1, n)都是比原始问题f(1, n)规模更小的问题,因此可以使用动态规划进行求解。
动态规划的状态为f(i, j),表示在范围[i, j]内确保胜利的最少金额。
当i = j时范围[i, j]只包含1个数字,则所选数字一定是范围内唯一的数字,不存在猜错的情况,因此,f(i, j)=0;当i > j 时,范围[i, j]不存在,f(i, j) = 0。
当i < j时,在范围[i, j]内第一次猜的数字可能是该范围内的任何一个数字。在第一次猜的数字是k的情况下(i <= k <= j),在范围[i, j]内确保胜利的最少金额是k + max(f(i, k-1), f(k+1, j))。需要遍历全部可能的k找到在范围[i, j]内确保胜利的最少金额,因此状态转移方程如下:
f ( i , j ) = m i n i < = k < = j ( k + m a x ( f ( i , k − 1 ) , f ( k + 1 , j ) ) ) f(i, j) = min_{i <= k <= j}(k+max(f(i, k-1), f(k+1, j))) f(i,j)=mini<=k<=j​(k+max(f(i,k−1),f(k+1,j)))
由于状态转移方程为根据规模小的子问题计算规模大的子问题,因此计算子问题的顺序为先计算规模小的子问题,后计算规模大的子问题,需要注意循环遍历的方向。

Java实现

class Solution {
    public int getMoneyAmount(int n) {
        int[][] f = new int[n+1][n+1];
        for (int i = n-1; i >= 1; i--) {
            for (int j = i + 1; j <= n; j++) {
                int minCost = Integer.MAX_VALUE;
                for (int k = i; k < j; k++) {
                    int cost = k + Math.max(f[i][k-1], f[k+1][j]);
                    minCost = Math.min(minCost, cost);
                }
                f[i][j] = minCost;
            }
        }
        return f[1][n];
    }
}
Python实现

class Solution:
    def getMoneyAmount(self, n: int) -> int:
        f = [[0] * (n+1) for i in range(n+1)]
        for i in range(n-1, 0, -1):
            for j in range(i+1, n+1):
                f[i][j] = min(k+max(f[i][k-1], f[k+1][j]) for k in range(i, j))
        return f[1][n]
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/490565.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号