问题描述



来源:LeetCode第1309题

难度:简单


给你一个字符串s,它由数字('0'-'9')和'#'组成。我们希望按下述规则将s映射为一些小写英文字符:


字符('a'-'i')分别用('1'-'9')表示。

字符('j'-'z')分别用('10#'-'26#')表示。

返回映射之后形成的新字符串。


题目数据保证映射始终唯一。


示例 1:


输入:s = "10#11#12"

输出:"jkab"

解释:"j" -> "10#" , "k" -> "11#" , "a" -> "1" , "b" -> "2".


示例 2:



输入:s = "1326#"

输出:"acz"


示例 3:



输入:s = "25#"

输出:"y"


示例 4:



输入:s =

"12345678910#11#12#13#14#15#16#17#18#19#20#21#22#23#24#25#26#"

输出:"abcdefghijklmnopqrstuvwxyz"



提示:


  • 1<=s.length<=1000
  • s[i]只包含数字('0'-'9')和'#'字符。
  • s是映射始终存在的有效字符串。



问题分析



这题是让把数字解码到字符,正常情况下如果从前往后遍历字符串s计算的时候有点麻烦,因为当遇到一个数字的时候不确定他是一个单独的数字还是和后面'#'结合的。所以我们可以逆向思维,从后往前遍历,当遇到一个数字的时候他就是一个单独的数字,当遇到符号'#'的时候我们需要往前截取两个数字,也就是说'#'和前面的两个数字他们三个是一伙的。原理比较简单,基本上没什么难度,我们来看下代码

public String freqAlphabets(String s) {
StringBuilder stringBuilder = new StringBuilder();
//字符串从后往前遍历
for (int i = s.length() - 1; i >= 0; i--) {
//如果遇到字符'#',就截取他前面的两个数字
if (s.charAt(i) == '#') {
stringBuilder.append((char) ('a' + Integer.parseInt(s.substring(i - 2, i)) - 1));
i -= 2;
} else {
stringBuilder.append((char) ('a' + s.charAt(i) - '1'));
}
}
//因为是从后往前遍历的,最后需要把结果反转一下
return stringBuilder.reverse().toString();
}