[LeetCode] Letter conbinations of a phone number算法-递归-回溯法

问题:

17  Letter conbinations of a phone number

测试数据:

边界控制:

图形化表述:

表达式表述:

算法:

import java.util.List;
import java.util.ArrayList;

/// 17. Letter Combinations of a Phone Number
/// https://leetcode.com/problems/letter-combinations-of-a-phone-number/description/
/// 时间复杂度: O(2^len(s))
/// 空间复杂度: O(len(s))
class Main {
    //利用数组索引实现匹配,而没有使用key-value
    private String letterMap[] = {
            " ",    //0
            "",     //1
            "abc",  //2
            "def",  //3
            "ghi",  //4
            "jkl",  //5
            "mno",  //6
            "pqrs", //7
            "tuv",  //8
            "wxyz"  //9
    };
    //全局变量,用于保存s
    private ArrayList<String> res;
     //调用主函数
    public List<String> letterCombinations(String digits) {
        //初始化
        res = new ArrayList<String>();
        //如果是空字符就返回不做处理
        if(digits.equals(""))
            return res;
        //调用递归函数,使用递归琢步向后生成相应的字符串 , index 代表索引开始位置,首先肯定是从0开始,而且生成的结果s也初始为空
        findCombination(digits, 0, "");
        return res;
    }


    // s中保存了此时从digits[0...index-1]翻译得到的一个字母字符串
    // 寻找和digits[index]匹配的字母, 获得digits[0...index]翻译得到的解
    private void findCombination(String digits, int index, String s){

        System.out.println(index + " : " + s);
        //索引指向了数字字符串的末尾,意味着已经遍历到底了, 此时获取到的s就是问题的一个解了,所以
        //应该把s保存起来,否则继续递归调用
        if(index == digits.length()){
            res.add(s);
            System.out.println("get " + s + " , return");
            return;
        }
        //c遍历的是数字字符串的索引对应值,如 digist=234, index =0,  c=2
        Character c = digits.charAt(index);
        assert  c.compareTo('0') >= 0 &&
                c.compareTo('9') <= 0 &&
                c.compareTo('1') != 0;
        //当前的数字字符对应的字母,如 2 对应了 abc
        String letters = letterMap[c - '0'];
        //对得到的字母进行遍历,如abc
        for(int i = 0 ; i < letters.length() ; i ++){
            System.out.println("digits[" + index + "] = " + c +
                    " , use " + letters.charAt(i));
            //因为已经处理了当前的数字字符串index,接下来要处理下一位的index  ,所以是index+1
            //s中保存了此时从digits[0...index-1]翻译得到的一个字母字符串
            //当遍历第二个字符时, 将第二个字符放在s的后面,从而基于一个新的字符串向下遍历
            findCombination(digits, index+1, s + letters.charAt(i));
        }

        System.out.println("digits[" + index + "] = " + c + " complete, return");

        return;
    }

    private static void printList(List<String> list){
        for(String s: list)
            System.out.println(s);
    }

    public static void main(String[] args) {
        printList((new Main()).letterCombinations("23"));
    }
}

感受:

        这里将最核心的代码贴出 :

private void findCombination(String digits, int index, String s){
    if(index == digits.length()){//递归终止条件
        res.add(s);
        return;
    }
    String letters = letterMap[digits.charAt(index) - '0'];
    for(int i = 0 ; i < letters.length() ; i ++){
        findCombination(digits, index+1, s + letters.charAt(i));
    }
    return;
}

        通过比较其他递归例题和算法,发现本题特别之处在于在递归中使用了for ,   相比于斐波那契数列, 阶乘, 汗塔塔 等,原因在于有本题的算法路径有一个"回溯"情况,以左半树为例  ,流程显示: 

类似问题:

1. restore ip addresses 

2.palindrome partitioning

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值