给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
class Solution {public int translateNum(int num) {}
}
动态规划解析:
字符串遍历
代码如下
class Solution {public int translateNum(int num) {String s = String.valueOf(num);int a = 1, b = 1;for(int i = 2; i <= s.length(); i++) {String tmp = s.substring(i - 2, i);int c = tmp.compareTo("10") >= 0 && tmp.compareTo("25") <= 0 ? a + b : a;b = a;a = c;}return a;}
}
使用数字求余节省空间
运用 求余 和 求整 运算实现,可实现 从右向左 的动态规划计算。而根据上述动态规划 “对称性” ,可知从右向左计算是正确的。
代码如下
class Solution {public int translateNum(int num) {int a = 1, b = 1, x, y = num % 10;while(num > 9) {num /= 10;x = num % 10;int tmp = 10 * x + y;int c = (tmp >= 10 && tmp <= 25) ? a + b : a;b = a;a = c;y = x;}return a;}
}
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
class Solution {public int lengthOfLongestSubstring(String s) {}
}
动态规划解析:
状态定义: 设动态规划列表 dp ,dp[j] 代表以字符 s[j] 为结尾的 “最长不重复子字符串” 的长度。
转移方程: 固定右边界 j,设字符 s[j] 左边距离最近的相同字符为 s[i] ,即 s[i]=s[j] 。
当 i<0 ,即s[j] 左边无相同字符,则 dp[j] = dp[j-1] + 1 ;
当 dp[j−1]
返回值: max(dp) ,即全局的 “最长不重复子字符串” 的长度。
动态规划 + 哈希表
哈希表统计: 遍历字符串 s 时,使用哈希表(记为 dic )统计 各字符最后一次出现的索引位置 。
左边界 i 获取方式: 遍历到s[j] 时,可通过访问哈希表 dic[s[j]]获取最近的相同字符的索引 i 。
代码如下
class Solution {public int lengthOfLongestSubstring(String s) {Map dic = new HashMap<>();int res = 0, tmp = 0, len = s.length();for(int j = 0; j < len; j++) {int i = dic.getOrDefault(s.charAt(j), -1); // 获取索引 idic.put(s.charAt(j), j); // 更新哈希表tmp = tmp < j - i ? tmp + 1 : j - i; // dp[j - 1] -> dp[j]res = Math.max(res, tmp); // max(dp[j - 1], dp[j])}return res;}
}