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