1 描述
2 思路
-
举个例子对于"239" 来说
2对应"abc"
3对应"def"
9对应"wxyz" -
那么在数学中想要展示它有多少种情况相当于是:
2的3种情况 乘 3的3种情况 乘 9的4种情况
如果在纸上画出来,就会发现它代表着一棵树 -
对于"239"来说根节点为起点,
第一个字符为’2’,那么它就有3条路可走假设走第一条路,走了’a’,
然后第二个字符是3,对应着有3条路,假设3走’d’
然后来到第三个字符’9’,它对应着4条路,假设走’w’ -
然后用一个变量来记录刚刚假设走的路,那么此变量走到最后一层结束后,所记录的字符串即为其中的一个结果
-
看下图 比如对于"23",那么它就有下图这些情况
-
因此本题,用回溯的方式来遍历整颗数,每次到最后一层时,将结果放进结果集的集合里去。
3 代码如何写
- 首先定义 存放结果的结果集 定义一个映射数组 比如strNumber[3]表示"def" 定义一个记录结果的字符串 比如path记录了"adw"
-
- 编写递归函数 对于"239" 来说它有3个数字,因此它有3层,
- 这里递归的终止条件:用一个变量记录当前层数,当大于上面"239"的三层时,就停止递归.然后将path记录的结果加入结果集
- 当前层数若没有超过上面"239"的三层时,就for循环当前层的数字对应的字符串
- 比如当前为第2层,那么就是数字’3’,它对应的就是"def",因此就遍历循环"def"的每个字符,将每个字符加入到path
- 然后在调用递归函数对每个字符进行操作
- 最后将path最后一个字符弹出,因为要回到上一层
- 具体代码解释详见注释
4 java代码
public class Solution {
//结果集
List<String> result = new ArrayList<>();
//字符映射数组
private String numberMap[];
//创建结果路径--比如"233"中的结果集其中一个就是"ade" 这里用path临时表示一个路径
StringBuilder path;
public List<String> letterCombinations(String digits) {
if (digits.isEmpty()) {
return result;
}
//创建映射数组-strNumber 这里strNumber[2]表示"abc" strNumber[3]表示"def"...
numberMap = new String[]{
"",
"",
"abc",
"def",
"ghi",
"jkl",
"mno",
"pqrs",
"tuv",
"wxyz"
};
path = new StringBuilder();
backTracking(digits, 0);
return result;
}
//回溯函数
private void backTracking(String digits, int index) {
//执行到digits数字末尾后时,就不执行了
if (index == digits.length()) {
result.add(path.toString());
return;
}
//c表示当前要循环的数字字符
char c = digits.charAt(index);
//找到对应数字字符在数组中对应的下标的字符串
//原理:比如找c是'2'那么它的ascii就是50 而0的ascii就是48,因此通过c - '0'就可以算出它和0的ascii的差值
// 这样算出差值是2,因此c是'2'的情况下就用差值表示c对应的数组下标是2
String letter = numberMap[c - '0'];
//遍历当前数字字符对应的字符串 比如 c是'2' --> "def" 遍历这个"def"的每个字符
for (int i = 0; i < letter.length(); i++) {
//将当前遍历到的字符加入path
path.append(letter.charAt(i));
//进行下一层
backTracking(digits, index + 1);
//当前层遍历完毕后,需要将path的最后一个字符pop掉
//因为此时要返回上一层
path.deleteCharAt(path.length() - 1);
}
}
}