【剑指offer】把数字翻译成字符串+礼物的最大价值+n个骰子的点数总和

🔥题目

给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请计算给出的数字有多少种不同的翻译方法。

输入:12258
输出:5
解释:12258有5种不同的翻译,分别是"bccfi", “bwfi”, “bczi”, “mcfi"和"mzi”

☘️解析

比较简单的动态规划。

一个易错点在于,"02"这样的组合并不能像"2"一样的被翻译,需要特判一下。

🧊代码
class Solution {
    public int translateNum(int num) {
        char[] arr = String.valueOf(num).toCharArray();
        int len = arr.length;
        int[] dp = new int[len + 1];
        // 初始化
        dp[0] = 1;
        dp[1] = 1;
        // 状态转移
        for (int i = 2; i < len + 1; i++) {
            if (arr[i - 2] == '0') {
                dp[i] = dp[i - 1];
            } else {
                int n = Integer.parseInt(String.valueOf(arr[i - 2]) + String.valueOf(arr[i - 1]));
                dp[i] = dp[i - 1] + (n < 26 ? dp[i - 2] : 0);
            }
        }
        return dp[len];
    }
}

 
 
 
 
 

🔥题目

在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?

输入: 
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
输出: 12
☘️解析

非常简单的动态规划。

写完之后,看一看是否可以进行滚动数组优化呢?

🧊代码
class Solution {
    public int maxValue(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int[][] dp = new int[m + 1][n + 1];
        for (int i = 1; i < m + 1; i++) {
            for (int j = 1; j < n + 1; j++) {
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
            }
        }
        return dp[m][n];
    }
}

 
 
 
 
 

🔥题目

把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。

输入: 1
输出: [0.16667,0.16667,0.16667,0.16667,0.16667,0.16667]

输入: 2
输出: [0.02778,0.05556,0.08333,0.11111,0.13889,0.16667,0.13889,0.11111,0.08333,0.05556,0.02778]

☘️解析

有些难度的动态规划。

dp[i][j]的含义是:用i个骰子得到总和为j的次数。

假如最后一次骰出的数字为k(for i in [1,6]),则状态转移方程为dp[i][j] += dp[i - 1][j - k]

🧊代码
class Solution {
    public double[] dicesProbability(int n) {
        // dp[i][j]的含义是:用i个骰子得到总和为j的次数
        int[][] dp = new int[n + 1][6 * n + 1];
        // 初始化
        for (int i = 1; i <= 6; i++) {
            dp[1][i] = 1;
        }
        // 状态转移
        for (int i = 2; i <= n; i++) {
            for (int j = i; j <= 6 * n; j++) {
                for (int k = 1; k <= 6 && k < j; k++) {
                    dp[i][j] += dp[i - 1][j - k];
                }
            }
        }
        // 概率
        double[] res = new double[5 * n + 1];
        double sum = Math.pow(6, n);
        for (int i = 0; i < res.length; i++) {
            res[i] = dp[n][i + n] / sum;
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值