这算是一个组合问题,就是从每一个数字的字母里选择一个数,组成一个全排列,首先想到的就是回溯算法。
回溯需要画一个相应的回溯树,这样比较容易理解这个过程,每一次递归调用函数就是树向下走一层,所以处理好这一层的关系和终止条件,那么这个题就很容易解出来,我们先看终止条件。
可以看出每个组合的长度和原来digits的长度相同,那么终止条件也就来了:
if(path.length() == digits.length())
{
result.add(path.toString());
}
下面简单画一下回溯树:
这里和普通的回溯有点区别,因为一个数字下面有3-4个字母可以选择,就用两层来表示一层,这样代码好写一些
for(int i = start ; i < digits.length() ; i++)
{
for(int j = 0 ; j < num.get( digits.charAt(i) - '0' - 2 ).length() ; j++)
{
path.append(num.get( digits.charAt(i) - '0' - 2 ).charAt(j));
search(num,digits,i + 1);
path.deleteCharAt(path.length() - 1);
}
}
总体代码如下:
class Solution {
List<String> result = new ArrayList<>();
StringBuilder path = new StringBuilder();
public List<String> letterCombinations(String digits) {
if(digits.length() == 0)
return result;
List<String> num = new ArrayList<>();
num.add("abc");
num.add("def");
num.add("ghi");
num.add("jkl");
num.add("mno");
num.add("pqrs");
num.add("tuv");
num.add("wxyz");
search(num , digits , 0);
return result;
}
private void search(List<String> num, String digits, int start)
{
if(path.length() == digits.length())
{
result.add(path.toString());
}
else
{
for(int i = start ; i < digits.length() ; i++)
{
for(int j = 0 ; j < num.get( digits.charAt(i) - '0' - 2 ).length() ; j++)
{
path.append(num.get( digits.charAt(i) - '0' - 2 ).charAt(j));
search(num,digits,i + 1);
path.deleteCharAt(path.length() - 1);
}
}
}
}
}
第一次没过那个空字符串所以在search函数前加上了:
if(digits.length() == 0)
return result;
效率还算不错