🔥题目
给定一个数字,我们按照如下规则把它翻译为字符串: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;
}
}