【leetcode随心刷】回溯套路:17. 电话号码的字母组合

228 阅读4分钟

咱们继续按照分类来肝leetcode回溯分类下的题目,一直按照同一个分类来刷,比较容易养成自己的规则。

今天的题目是17. 电话号码的字母组合 :https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/

题意

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

思路推演

看到这道题应该可以想到咱们第一篇回溯文章《黑板上排列组合你舍得解开吗?》中的组合。这道题拨开花里胡哨的外表就是从给定的数组里面选数组,进行组合。

如果给定的数字是“23”,那么就是从给定的两个数组[a,b,c]和[d,e,f]中各选一个数组看有多少种组合而已。到这里,一旦发现是排列组合的题目我们都可以通过回溯,也就是深度优先遍历拿到他所有的可能性,再配合有规则的剪枝,我们就可以得到最终的答案了。

使用回溯来解决问题,那们就不墨迹了,直接上最开始的框架。

选择与回退:从数字对应的列表里选择一个字符,然后递归遍历下一个数字对应的情况。当递归完下一个字符的情况的时候再回到这一层,回到本层遍历其他字符。 终止条件:选择的列表长度等于给定数字的个数的时候代表选择完成。 过滤条件:这道题里面走得每一步都是唯一的,不需要过滤条件。

因为这道题只给到了数字部分,我们还是需要手动初始化一下数组,一遍我们后续的工作。

最后还需要注意下边界条件,如果传一个空串则需要返回一个空列表。

最后见如下代码,以及注释。

class Solution {
    List<List<String>> digitsList = new ArrayList<>();
    List<String> res = new ArrayList<>();
    public List<String> letterCombinations(String digits) {
        //边界条件
        if(digits == null || digits.isEmpty()) {
            return res;
        }
        //初始化数字和字母的对应列表,直接使用下标来代表数字。
        digitsList.add(new ArrayList<>());
        digitsList.add(new ArrayList<>());
        digitsList.add(Arrays.asList("a""b""c"));
        digitsList.add(Arrays.asList("d""e""f"));
        digitsList.add(Arrays.asList("g""h""i"));
        digitsList.add(Arrays.asList("j""k""l"));
        digitsList.add(Arrays.asList("m""n""o"));
        digitsList.add(Arrays.asList("p""q""r""s"));
        digitsList.add(Arrays.asList("t""u""v"));
        digitsList.add(Arrays.asList("w""x""y""z"));
        
        dfs(digits, 0"", res);
        return res;
    }

    private void dfs(String digits, int index, String path, List<String> res) {
        //终止条件
        if(path.length() == digits.length()) {
            res.add(new String(path));
            return;
        }

        int num = Integer.valueOf(digits.substring(index, index + 1));
        //根据数字遍历这个数字对应字符的列表
        for(int i = 0; i < digitsList.get(num).size(); i++) {
            String digit = digitsList.get(num).get(i);
            //选择以及回退
            path += digit;
            dfs(digits, index + 1, path, res);
            path = path.substring(0, path.length() -1);
        }
    }
}

最后

打完收工。明天继续搞回溯分类下的题目leetcode79:https://leetcode-cn.com/problems/word-search/,继续巩固回溯套路。一起刷题的朋友可以先看下题意了解一下。

欢迎关注公众号【理解并背诵君】,让我们一起开心刷题。