375、猜数字大小II

  1. 375、猜数字大小II
    1. 示例:
  • 题解
    1. 1、暴力求解
    2. 2、优化的暴力递归
    3. 3、动态规划
    4. 4、优化的动态规划
    5. 5、1~2ms 记忆化递归
  • 375、猜数字大小II

    我们正在玩一个猜数游戏,游戏规则如下:

    我从 1 到 n 之间选择一个数字,你来猜我选了哪个数字。

    每次你猜错了,我都会告诉你,我选的数字比你的大了或者小了。

    然而,当你猜了数字 x 并且猜错了的时候,你需要支付金额为 x 的现金。直到你猜到我选的数字,你才算赢得了这个游戏。

    示例:

    n = 10, 我选择了8.
    
    第一轮: 你猜我选择的数字是5,我会告诉你,我的数字更大一些,然后你需要支付5块。
    第二轮: 你猜是7,我告诉你,我的数字更大一些,你支付7块。
    第三轮: 你猜是9,我告诉你,我的数字更小一些,你支付9块。
    
    游戏结束。8 就是我选的数字。
    
    你最终要支付 5 + 7 + 9 = 21 块钱。
    

    给定 n ≥ 1,计算你至少需要拥有多少现金才能确保你能赢得这个游戏。

    题解

    1、暴力求解

    $cost(1,n) = i+max(cost(1,i - 1),cost(i+1,n)) low <= i <= high$

    • 代码
    // java
    class Solution {
        public int getMoneyAmount(int n) {
            return calculate(1,n);
        }
    
        private int calculate(int low, int high) {
            // 递归结束条件
            if (low >= high) {
                return 0;
            }
            int minres = Integer.MAX_VALUE;
            // 递归搜索
            for (int i = low,i <= high;i++) {
                int res = i + Math.max(calculate(low,i-1),calculate(i+1,high));
                int minres = Math.min(res,minres);
            }
            return minres;
        }
    }
    

    2、优化的暴力递归

    $cost(1,n) = i+max(cost(1,i - 1),cost(i+1,n)) (low+high)/2 <= i <= high$

    • 代码
    // java
    class Solution {
        public int getMoneyAmount(int n) {
            return calculate(1,n);
        }
    
        private int calculate(int low, int high) {
            // 递归结束条件
            if (low >= high) {
                return 0;
            }
            int minres = Integer.MAX_VALUE;
            // 递归搜索
            for (int i = (low+high)/2,i <= high;i++) {
                int res = i + Math.max(calculate(low,i-1),calculate(i+1,high));
                int minres = Math.min(res,minres);
            }
            return minres;
        }
    }
    

    3、动态规划

    • 二维动归
    • 自下向上

    $cost(i,j) = pivot+max(cost(i,pivot - 1),cost(pivoty+1,len)) i <= pivot <= len,len = j-i+1$

    $dp(i,j) = min_{pivots(i,j)}(pivot+max(dp(1,pivot - 1),dp(pivoty+1,len))) i <= pivot <= len,len = j-i+1$

    • 代码
    // java
    class Solution {
        public int getMoneyAmount(int n) {
            int[][] dp = new int[n+1][n+1];
            for (int len = 2;len <= n;len++) {
                for (int start = 1;start <= n - len + 1;start++) {
                    int minres = Integer.MAX_VALUE;
                    for (int piv = start;piv < start+ len -1;piv++) {
                        int res = piv + Math.ma(dp[start][piv-1],dp[piv+1][start + len - 1]);
                        minres = Math.min(res,minres);
                    }
                }
            }
            return dp[1][n];
        }
    }
    

    4、优化的动态规划

    • 二维动归
    • 自下向上

    $dp(i,j) = min_{pivots(i+(len-1)/2,j)}(pivot+max(dp(1,pivot - 1),dp(pivoty+1,len))) i+len/2 <= pivot <= i+len,len = j-i+1$

    • 代码
    // java
    class Solution {
        public int getMoneyAmount(int n) {
            int[][] dp = new int[n+1][n+1];
            for (int len = 2;len <= n;len++) {
                for (int start = 1;start <= n - len + 1;start++) {
                    int minres = Integer.MAX_VALUE;
                    // 求最优的minres
                    for (int piv = start+(len-1)/2;piv < start+ len -1;piv++) {
                        int res = piv + Math.max(dp[start][piv-1],dp[piv+1][start+len-1]);
                        minres = Math.min(res,minres);
                    }
                    // 更新dp数组
                    dp[start][start+len -1] = minres;
                }
            }
            return dp[1][n];
        }
    }
    

    5、1~2ms 记忆化递归

    class Solution {
        public int getMoneyAmount(int n) {
            if(n == 1) return 0;
            int[][] memo = new int[n+1][n+1];
            return calculateMoney(1,n,memo);
    
        }
        private int calculateMoney(int low, int high, int[][] memo) {
            if (low >= high) return 0;
            if (memo[low][high] != 0) return memo[low][high];
            int minRes = Integer.MAX_VALUE;
            for (int i = (low+high)/2; i <= high; i++) {
                int res = i + Math.max(calculateMoney(i + 1, high, memo), calculateMoney(low, i - 1, memo));
                minRes = Math.min(res, minRes);
            }
            memo[low][high] = minRes;
            return minRes;
        }
    }
    

    转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com

    💰

    Title:375、猜数字大小II

    Count:904

    Author:攀登

    Created At:2020-07-26, 00:19:44

    Updated At:2024-06-15, 15:52:32

    Url:http://jiafeimao-gjf.github.io/2020/07/26/375%E3%80%81%E7%8C%9C%E6%95%B0%E5%AD%97%E5%A4%A7%E5%B0%8FII/

    Copyright: 'Attribution-non-commercial-shared in the same way 4.0' Reprint please keep the original link and author.

    ×

    Help us with donation