LeetCode 17. Letter Combinations of a Phone Number 电话号码的字母组合(Java)

题目:

Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent.

A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.
LeetCode 17. Letter Combinations of a Phone Number 电话号码的字母组合(Java)_第1张图片

Example:
Input: “23”
Output: [“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].

Note:
Although the above answer is in lexicographical order, your answer could be in any order you want.

解答:

解法一:HashMap + 多重循环

这道题自己只想到了暴力解法。
即将所有数字对应的字母通过循环依次取出来,然后进行嵌套遍历的方法。借助 HashMap 存储数字与字母间的键值关系。

其中循环嵌套思路为:

  1. 第一层循环:循环 digits.length(),依次取出输入的每个数字,并利用 HashMap 中的 get() 方法取出对应的字母value 值 substr
  2. 再将其后面一个数字对应的 value 值也取出来,进行嵌套循环,实现排列组合。
    如第一个数字 2,对应的是 abc,此时 list 数组中的值就是 [a,b,c],循环下一个数字 3,对应的是 def,遍历 list 中的值,分别将 a,b,c 拼上d,e,f,依次循环,最后返回 list
class Solution {
    public List<String> letterCombinations(String digits) {
        Map<Character, String> map = new HashMap<>();
        map.put('2', "abc");
        map.put('3', "def");
        map.put('4', "ghi");
        map.put('5', "jkl");
        map.put('6', "mno");
        map.put('7', "pqrs");
        map.put('8', "tuv");
        map.put('9', "wxyz");     
        List<String> list = new ArrayList<>();
        if(digits.length()==0) {
            return list;
        }
        list.add("");
        for(int i=0; i<digits.length(); i++) {
            List<String> temp = new ArrayList<>();
            String substr = map.get(digits.charAt(i));            
            for(String str: list) {
                for(int j=0; j<substr.length(); j++) {
                    String strsum = str + substr.charAt(j);
                    temp.add(strsum);
                }
            }
            list = temp;
        }
        return list;
    }
}

在这里插入图片描述

解法二:队列 + 循环

或者,也可利用队列先进先出的性质进行横向组合
思路:

  1. 首先取出输入中的第一个数,找到它所代表的字符串,遍历字母并依次放入队列中
  2. 接着取出输入的下一个数,找到它所代表的字符串,队列依次出队,并依次与当前字符串中代表的每个字母进行组合,并再次入队
  3. 当队列里所有字符串长度 == 输入的字符串长度时,即完成所有组合。因此可通过 res.peek().length() 获取队列头部元素长度,判断是否与 digits.length() 相同
    (因此在第二步中,即可通过队列里的字符长度,获取输入的下一个数)
class Solution {
    public List<String> letterCombinations(String digits) {
        LinkedList<String> res = new LinkedList<>();
        String[] map = new String[] {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
        if(digits.length()==0) {
            return res;
        }
        res.add("");
        while(res.peek().length() != digits.length()) {
            String temp = res.pop();
            String str = map[digits.charAt(temp.length()) - '0'];
            for(char c: str.toCharArray()) {
                res.add(temp + c);
            }
        }
        return res;
    }
}

这种方法代码简洁一些,但与解法一思路相同,因此时间复杂度也相同。
在这里插入图片描述

解法三:回溯法

“回溯”算法:即一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择。
大部分回溯问题都离不开几个元素:递归、深度优先以及全排列

分析题目可知:题目的输出近似是一种将满足条件所有排列都枚举出来。即每次固定一个位置改变其他位置
若输入的数为“234”,那么第一个字符有三种选择,分别是“a”,“b”,“c”,如果第一个字符选 a,那么第二个字符也有 3 种选择,而选择好第二个字符后,第三个字符又有3种选择…以此类推会发现,这个逻辑思路与树结构很像,都是一层层增多,每一层的一个节点都对应有多个孩子节点。
因此可以用“回溯”的思路求解。

class Solution {
    private static final String[] map = new String[] {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
    public List<String> letterCombinations(String digits) {
        List<String> res = new ArrayList<>();        
        if(digits.length()==0) {
            return res;
        }
        doCombination(new StringBuffer(), res, digits);
        return res;
    }
    private void doCombination(StringBuffer str, List<String> res, String digits) {
    	//str达到预期长度,即完成一次组合,就将str保存进res中
        if(str.length() == digits.length()) {
            res.add(str.toString());
            return;
        }
        //读取当前digits遍历到的元素对应的可选字符集
        String substr = map[digits.charAt(str.length())-'0'];
        //遍历可选字符集,每次固定当前位置的字符,再进行下一位的字符选择
        for(char c: substr.toCharArray()) {
            str.append(c);  //添加
            doCombination(str, res, digits);  // 递归
            str.deleteCharAt(str.length() - 1);  //删除
        }
    }
}

在这里插入图片描述

你可能感兴趣的:(LeetCode)