这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
8月8日,中国队以88枚奖牌收官东京奥运会。虽然最后时刻金牌榜被美国反超,不过已经是很满意的结局了。最后相差这1块金牌,可能会让乒乓球混双项目失去的金牌更加膈应。有时候人生就是这样,虽然准备充分也尽力了,可能一些自己无法把控的外部因素,会让结果走向另外一个方向
昨天立下的Flag,今天算是没倒,出去锻炼了好一会儿,接下来几天继续加油吧。
今天继续刷leetcode的第17题,题目不难,但是看到一个新的解法有点意思。
题目
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = ""
输出:[]
示例 3:
输入:digits = "2"
输出:["a","b","c"]
思路
没错,最简单的思路就是直接暴力遍历,对于每个数字,都可能对应3-4个字母,直接暴力枚举就行。不过因为数字长度是不确定的,所以不能直接for,可以写个递归来处理。这种方法没什么可讲的,就是看这个递归怎么写而已,介绍一种另外的思路。
给定了一个数字串之后,可以看作是一个n位的数字,但是不是10进制,是1个3进制或者4进制的数字(7和9可以代表4个字母),每一位上的数值就是代表可选字母的第几个(从第0个开始)。这样的话,可以先计算出所有的可能性M,然后遍历0M-1,代表第0M-1种可能,第k种可能,就把k翻译到这个n位数,这样的话,每1位都会有唯一对应的字母。这里有个技巧是,k翻译成这个n位数的时候,是从最低位开始翻译的,所以最后要把整个字符串反转过来。
下面用 275 来演示一下:
2 -> abc 3种可能
7 -> pqrs 4种可能
5 -> jkl 3种可能
所以总共的可能数 = 3 * 4 * 3 = 36
遍历0~35:
第0种可能,翻译成3为数 000,对应的字符串为apj
第1种可能,翻译成3为数 001,对应的字符串为apk
第2种可能,翻译成3为数 002,对应的字符串为apl
第3种可能,翻译成3为数 010,对应的字符串为aqj
...
第12种可能,翻译成3为数 100,对应的字符串为bpj
...
第35种可能,翻译成3为数 232,对应的字符串为csl
Java版本代码
class Solution {
public List<String> letterCombinations(String digits) {
Map<Character, String> map = new HashMap<>();
map.put('2', "abc");
map.put('3', "def");
map.put('4', "ghi");
map.put('5', "jkl");
map.put('6', "mno");
map.put('7', "pqrs");
map.put('8', "tuv");
map.put('9', "wxyz");
List<String> ans = new ArrayList<>();
int len = digits.length();
if (len == 0) {
return ans;
}
// 总共可能的情况数
int count = 1;
for (int i = 0; i < len; i++) {
char digChar = digits.charAt(i);
String letters = map.get(digChar);
count *= letters.length();
}
// 这是一个三进制或者四进制的数,不同的位可能进制不同
for (int index = 0; index < count; index++) {
StringBuilder item = new StringBuilder();
int lastNum = index;
// 这里因为从低位开始计算比较方便,所以要反过来
for (int j = len-1; j >=0; j--) {
char digChar = digits.charAt(j);
String letters = map.get(digChar);
int lettersLen = letters.length();
item.append(letters.charAt(lastNum % lettersLen));
lastNum /= lettersLen;
}
// 别忘记这里把字符串再反转过来
ans.add(item.reverse().toString());
}
return ans;
}
}