电话号码的字母组合(力扣第17题)
题目:
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
分析:
这里每一个数字可以认为代表一个点,而这个点是一个包含几个字母的集合,那么从一个数字到另一个数字本质就是寻求从这个数字包含的字母集合中挑选一个字母然后与下一个数字包含的字母集合挑选一个字母最终组合成字母字符串的过程,相当于是求不同字母集合之间的排列组合,只不过每一个数字包含的字母集合每次排列时只能取出一个字母参与排列。那么我们就可以选用DFS算法进行搜索,只不过现在不再是求可达性的问题了,而是我们现在要通过DFS算法求出所有的不同的连通分量,连通分量之间只要有一个顶点不一样,那就是不同的。
所以我们在进行DFS搜索的时候,如果在某个方向到达尽头了,此时我们并不是立刻停止操作,而是记录好走到尽头时字母的排列组合情况,然后回退到当前顶点的”父“节点,也就是进行回溯操作,然后这个”父“节点,继续选择其他方向(其他字母)进行搜索,这个父亲节点如果所有方向都走完了,那么就继续回溯,直到起始点的方向也都走完为止,此时所有的字母排列情况都求出来了,也就是我们的最终结果。
private String[] graph; public List<String> letterCombinations(String digits) { if (digits == null || digits.length() == 0){ return new ArrayList<>(); } ArrayList<String> resList = new ArrayList<>(); graph = new String[]{"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"}; StringBuilder middleres = new StringBuilder(); findStrByDFS(resList,digits,middleres); return resList; } private void findStrByDFS(List<String> resList,String digits,StringBuilder middleres){ if (middleres.length() == digits.length()){ resList.add(middleres.toString()); return; } int curDigist = digits.charAt(middleres.length()) - '0'; for (char c : graph[curDigist].toCharArray()) { middleres.append(c); // 前进 findStrByDFS(resList,digits,middleres); middleres.deleteCharAt(middleres.length() - 1 ); // 回溯 } }
middleres主要负责记录搜索过程中的中间结果,它的初始值为0,每经过一个数字,因为要挑选一个字母加入到这个中间结果中,所以长度就加1,所以middleres的长度值和当前正在遍历的数字在其字符串中的索引值是相同且同步变化的,所以可以通过middleres的长度值来获取当前遍历的是哪个数字,然后将这个数字转换为整型时,再获取这个数字包含了哪些字母,然后挑选某个字母继续向下搜索。