[Leetcode][第17题][JAVA][电话号码的字母组合][回溯]
【問題描述】[中等]
【解答思路】
用哈希表/數組存儲每個數字對應的所有可能的字母,然后進行回溯操作。
回溯過程中維護一個字符串,表示已有的字母排列(如果未遍歷完電話號碼的所有數字,則已有的字母排列是不完整的)。該字符串初始為空。每次取電話號碼的一位數字,從哈希表中獲得該數字對應的所有可能的字母,并將其中的一個字母插入到已有的字母排列后面,然后繼續處理電話號碼的后一位數字,直到處理完電話號碼中的所有數字,即得到一個完整的字母排列。然后進行回退操作,遍歷其余的字母排列。
回溯算法用于尋找所有的可行解,如果發現一個解不可行,則會舍棄不可行的解。在這道題中,由于每個數字對應的每個字母都可能進入字母組合,因此不存在不可行的解,直接窮舉所有的解即可。
1. 回溯 哈希表
class Solution {public List<String> letterCombinations(String digits) {List<String> combinations = new ArrayList<String>();if (digits.length() == 0) {return combinations;}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(combinations, phoneMap, digits, 0, new StringBuffer());return combinations;}public void backtrack(List<String> combinations, Map<Character, String> phoneMap, String digits, int index, StringBuffer combination) {if (index == digits.length()) {combinations.add(combination.toString());} else {char digit = digits.charAt(index);String letters = phoneMap.get(digit);int lettersCount = letters.length();for (int i = 0; i < lettersCount; i++) {combination.append(letters.charAt(i));backtrack(combinations, phoneMap, digits, index + 1, combination);combination.deleteCharAt(index);}}} }2. 回溯 數組存儲
class Solution {// 數字到號碼的映射private String[] map = {"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};// 路徑private StringBuilder sb = new StringBuilder();// 結果集private List<String> res = new ArrayList<>();public List<String> letterCombinations(String digits) {if(digits == null || digits.length() == 0) return res;backtrack(digits,0);return res;}// 回溯函數private void backtrack(String digits,int index) {if(sb.length() == digits.length()) {res.add(sb.toString());return;}String val = map[digits.charAt(index)-'2'];for(char ch:val.toCharArray()) {sb.append(ch);backtrack(digits,index+1);sb.deleteCharAt(sb.length()-1);}} }【總結】
1. 回溯遞歸通用模板,即用一個臨時數組temp 來保存當前選出的子序列,使用cur 來表示當前位置的下標,在 dfs(cur, nums) 開始之前,[0,cur?1] 這個區間內的所有元素都已經被考慮過,而[cur,n] 這個區間內的元素還未被考慮。在執行 dfs(cur, nums) 時,我們考慮 cur 這個位置選或者不選,如果選擇當前元素,那么把當前元素加入到temp 中,然后遞歸下一個位置,在遞歸結束后,應當把temp 的最后一個元素刪除進行回溯;如果不選當前的元素,直接遞歸下一個位置。
List<List<Integer>> ans = new ArrayList<List<Integer>>(); List<Integer> temp = new ArrayList<Integer>(); public void dfs(int cur, int[] nums) {if (cur == nums.length) {// 判斷是否合法,如果合法判斷是否重復,將滿足條件的加入答案if (isValid() && notVisited()) {ans.add(new ArrayList<Integer>(temp));}return;}// 如果選擇當前元素temp.add(nums[cur]);dfs(cur + 1, nums);temp.remove(temp.size() - 1);// 如果不選擇當前元素dfs(cur + 1, nums); }2.回溯相關題目
[Leetcode][第491題][JAVA][遞增子序列][回溯][RK算法]
[Leetcode][第679題][JAVA][24點游戲][回溯][暴力]
[Leedcode][JAVA][第46題][全排列][回溯算法]
[Leetcode][第93題][JAVA][復原IP地址][剪枝][回溯]
[劍指offer]面試題第[38]題[JAVA][字符串的排列][回溯法]
[劍指offer][JAVA]面試題第[34]題[二叉樹中和為某一值的路徑][回溯]
[Leetcode][第17題][JAVA][電話號碼的字母組合][回溯]
參考鏈接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/solution/dian-hua-hao-ma-de-zi-mu-zu-he-by-leetcode-solutio/
總結
以上是生活随笔為你收集整理的[Leetcode][第17题][JAVA][电话号码的字母组合][回溯]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle-备份工具exp-imp
- 下一篇: [递归]一文看懂递归