返回
电话号码组合的深度优先探索之旅
后端
2023-09-10 21:24:31
在计算机科学中,通常我们可以通过多种途径求解一道算法题,就好比去一个地方,你可以坐飞机,也可以坐火车。不同的方法有着不同的效率,这里想说的是,算法的解题和实际生活中,在做决策的时候,非常相似。而对于一道算法题,有很多种解法,不同的解法会有着不同的效率,你如何选择,则需要考虑很多实际情况。同样,选择好的算法,同样也是如此。
很多时候,我们会被题目的外在表现所迷惑,很容易的就会掉进出题者的圈套里。比如,这道题,电话号码组合,你会发现,这是一道典型的哈希表题,毕竟,已经给你把数字和字母的对应关系都列出来了,而且你只需要把这些数字翻译成字母组合。所以,很明显,这是一道哈希表题,我们只需要把数字映射成相应的字母,然后进行组合即可。
于是乎,你就开始在哈希表的框架下写程序,你会发现,好像确实可以搞定。但是,在实际运行过程中,你会发现效率不是那么理想,然后你会发现,这其实是典型的深度优先遍历题,因为,每一个数字,都有很多可能的组合。比如,数字2可以组合成a,b,c,那对于一个四位的数字,就有3^4种组合。我们逐个去试,当然会很慢。
所以,在做算法题的时候,一定要保证自己对算法,对数据结构,都有一个深入的了解,然后在真正的开始写代码前,应该先思考一下这道题的特性,应该用什么算法去解决,这样才能在解题的道路上得心应手,轻松应对出题者的套路。
当然,在你的职业生涯中,会有各种各样的算法题等着你去挑战,如果你只是记住了解题的思路,而不是真正理解了算法背后的原理,你会发现,你还是无法应对所有的题目。所以,在这里,我还是建议大家把时间多花在基础算法的学习上。
最后,附上这道题的深度优先遍历解法,希望大家能够理解,算法,不仅仅是学习,更是艺术。
public static List<String> letterCombinations(String digits) {
LinkedList<String> ans = new LinkedList<String>();
if(digits.isEmpty()) {
return ans;
}
Map<Character, String> phoneMap = new HashMap<Character, String>() {
{
put('2', "abc");
put('3', "def");
put('4', "ghi");
put('5', "jkl");
put('6', "mno");
put('7', "pqrs");
put('8', "tuv");
put('9', "wxyz");
}
};
backtrack(ans, phoneMap, digits, 0, new StringBuilder());
return ans;
}
public static void backtrack(LinkedList<String> ans, Map<Character, String> phoneMap, String digits, int index, StringBuilder sb) {
if(index == digits.length()) {
ans.add(sb.toString());
return;
}
char digit = digits.charAt(index);
String letters = phoneMap.get(digit);
for(int i = 0; i < letters.length(); i++) {
sb.append(letters.charAt(i));
backtrack(ans, phoneMap, digits, index + 1, sb);
sb.deleteCharAt(sb.length() - 1);
}
}