暴力解法(Java)
核心思想: 三层for循环依次将digits中各个数字对应的字母组合中的所有字母依次拼接,拼接的方式是先依次从当前的结果集中取出所有字母组合,再依次拼接下一个数字对应的字母组合中的所有字母,最后将拼接后的字母组合放入结果集。
class Solution {
public List<String> letterCombinations(String digits) {
List<String> resList = new ArrayList<>();//结果集
if(digits==null || digits.length()==0) {
return resList;
}
resList.add("");//用于拼接单个字母
String[] letters = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};//数字0-9对应的字母组合
for(int i = 0; i < digits.length(); i++){
String letter = letters[digits.charAt(i) - '0'];//获取下一个数字对应的字母组合
int size = resList.size();//当前结果集的大小
//先依次从当前的结果集中取出所有字母组合
for(int j = 0; j < size; j++){
StringBuilder sb = new StringBuilder(resList.remove(0));
//再依次拼接下一个数字对应的字母组合中的所有字母
for(int k = 0; k < letter.length(); k++){
resList.add(sb.append(letter.charAt(k)).toString());//最后将拼接后的字母组合放入结果集
sb.deleteCharAt(sb.length() - 1);//回到拼接前的状态
}
}
}
return resList;
}
}
回溯法(Java)
核心思想: 亦可称为深度优先遍历(DFS),根节点为空字符串(“”),digits中的每一个数字对应的字母组合中的字母构成分支节点(一个数字对应树的一层),最后一个数字对应的字母组合中的字母构成叶子节点,求结果集的过程就是求从根节点到各个叶子节点的路径上的节点字母的组合。
class Solution {
public List<String> letterCombinations(String digits) {
List<String> resList = new ArrayList<>();//结果集
if(digits==null || digits.length()==0) {
return resList;
}
String[] letters = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};//数字0-9对应的字母组合
getResultList(resList, letters, digits, new StringBuilder(), 0);//从根节点开始遍历
return resList;
}
//回溯法求从根节点到各个叶子节点的路径上的节点字母的组合
void getResultList(List<String> resList, String[] letters, String digits, StringBuilder sb, int index) {
//判断是否遍历到叶子节点
if(index == digits.length()) {
resList.add(sb.toString());//若是,则将从根节点到叶子节点的路径上的节点字母的组合放入结果集
return;
}
String letter = letters[digits.charAt(index) - '0'];//获取树的index层的各个节点字母
for(int i = 0; i < letter.length(); i++) {
sb.append(letter.charAt(i));//拼接当前层的节点字母
getResultList(resList, letters, digits, sb, index + 1);//拼接下一层的节点字母
sb.deleteCharAt(sb.length() - 1);//回到拼接前的状态
}
}
}