递归3

139 阅读3分钟

规定1和A对应,2和B对应,3和C对应...

那么一个数字字符串比如”111“就可以转化为:

“AAA","KA","AK"

给定一个只有数字字符组成的字符串str,返回有多少种转化结果。

分析:众所周知,算法面试的递归套路一共有四种,只有5%不在其中,这是一道典型的从左往右的递归题目。

求转换结果:
如果第一个位置是1,那么就有两种选择,要不要看第二个位置,如果不看,那么就到第二个位置决策,如果看,那么就到第三个位置决策
如果第一个位置是2,那么就有两种选择,要不要看第二个位置,如果不看,那么就到第二个位置决策,如果看,又有两种选择,如果第二个位置的数小于7,那么到第三个位置决策,如果大于6,那么到第二个位置决策
如果第一个位置大于2,那么直接到第二个位置决策

求数量:
base case: 如果i来到length表明已经找到了一条转换结果返回1,如果i位置的值是0字符,转换不了直接返回0表示0种结果
如果第一个位置是1,那么就有两种选择,要不要看第二个位置,如果不看,那么直接返回从第二个位置开始转换的所有结果,如果看,那么返回从第二个位置开始转换的所有结果+从第三个位置开始转换的所有结果
如果第一个位置是2,那么就有两种选择,要不要看第二个位置,如果不看,那么直接返回从第二个位置开始转换的所有结果,如果看,又有两种选择,如果第二个位置的数小于7,那么返回从第二个位置开始转换的所有结果+从第三个位置开始转换的所有结果,如果大于6,那么直接返回从第二个位置开始转换的所有结果
如果第一个位置大于2,那么直接返回从第二个位置开始转换的所有结果

代码:

public class Class1 {
    public static void main(String[] args) {
        String s = "1112123312121212121211222121";
        char[] chars = s.toCharArray();
        List<String> sequences = new ArrayList<String>();
        System.out.println("sequences = " + sequences.size());

        int process = process(chars, 0);
        System.out.println("process = " + process);
    }



    /**
     * 求所有转换结果
     * @param chars 字符数组
     * @param position 从第i个位置转换
     * @param allResult 所有结果
     * @param currentResult 当前结果
     */
    private static void changeResult(char[] chars,int position,List<String> allResult,String currentResult){
        HashMap<String,String> map = new HashMap<String, String>();
        map.put("1","A");
        map.put("2","B");
        map.put("3","C");
        map.put("4","D");
        map.put("5","E");
        map.put("6","F");
        map.put("7","G");
        map.put("8","H");
        map.put("9","I");
        map.put("10","J");
        map.put("11","K");
        map.put("12","L");
        map.put("13","M");
        map.put("14","N");
        map.put("15","O");
        map.put("16","P");
        map.put("17","Q");
        map.put("18","R");
        map.put("19","S");
        map.put("20","T");
        map.put("21","U");
        map.put("22","V");
        map.put("23","W");
        map.put("24","X");
        map.put("25","Y");
        map.put("26","Z");


        if(position == chars.length){
            allResult.add(currentResult);
            return;
        }

        if(chars[position] == '1'){
            //不看第二个位置

            if(position+1 < chars.length){
                currentResult += map.get(chars[position]+"");
                changeResult(chars,position+1,allResult,currentResult);
            }else{
                currentResult += map.get(chars[position]+"");
                allResult.add(currentResult);
                return;
            }

            //看第二个位置
            if(position+1 < chars.length && position+2 < chars.length){
                currentResult += map.get(chars[position]+""+chars[position+1]);
                changeResult(chars,position+2,allResult,currentResult);
            }else if(position+1 < chars.length && position+2 >= chars.length){
                currentResult += map.get(chars[position]+""+chars[position+1]);
                allResult.add(currentResult);
                return;
            }else{
                return;
            }


        }

        if(chars[position] == '2'){
            //不看第二个位置
            if(position+1 < chars.length){
                currentResult += map.get(chars[position]+"");
                changeResult(chars,position+1,allResult,currentResult);
            }else{
                currentResult += map.get(chars[position]+"");
                allResult.add(currentResult);
                return;
            }

            //看第二个位置
            if(chars[position+1] <= '6') {
                if(position+1 < chars.length && position+2 < chars.length){
                    currentResult += map.get(chars[position]+""+chars[position+1]);
                    changeResult(chars,position+2,allResult,currentResult);
                }else if(position+1 < chars.length && position+2 >= chars.length){
                    currentResult += map.get(chars[position]+""+chars[position+1]);
                    allResult.add(currentResult);
                    return;
                }else{
                    return;
                }
            }else{
                if(position+1 < chars.length){
                    currentResult += map.get(chars[position]+"");
                    changeResult(chars,position+1,allResult,currentResult);
                }else{
                    currentResult += map.get(chars[position]+"");
                    allResult.add(currentResult);
                    return;
                }
            }
        }

        if(chars[position] > '2'){
            //不看第二个位置
            if(position+1 < chars.length){
                currentResult += map.get(chars[position]+"");
                changeResult(chars,position+1,allResult,currentResult);
            }else{
                currentResult += map.get(chars[position]+"");
                allResult.add(currentResult);
                return;
            }
        }
    }

    /**
     * 求转换数量
     * @param str 字符数组
     * @param i 从第i个位置转换
     * @return
     */
    private static int process(char[] str,int i){
        if(i == str.length){
            return 1; //找到了一种转换结果
        }

        if(str[i] == '0'){
            return 0; //'0'转换不了
        }

        if(str[i] == '1'){
            int res = process(str,i+1); //不带下一个位置转换的所有结果
            if(i+1 < str.length){
                res += process(str,i+2);//带下一个位置转换的所有结果
            }
            return res;
        }

        if(str[i] == '2'){
            int res = process(str,i+1); //不带下一个位置转换的所有结果
            if(i+1 < str.length && str[i+1] <= '6'){
                res += process(str,i+2);//带下一个位置转换的所有结果
            }
            return res;
        }

        return process(str,i+1); //如果是大于二,没得选择,不带下一个位置转换的所有结果
    }

}