0
点赞
收藏
分享

微信扫一扫

动态规划之数字与字符串对应问题

题目

规定1和A对应、2和B对应、3和C对应...26和Z对应。

那么一个数字字符串比如"111"就可以转化为:"AAA"、"KA"和"AK"。

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

思路一:暴力递归

转化的时候要么取一个字符,要么取两个字符。注意:’0‘的情况是没有意义的,如果两个字符时,不能超过26,只有26个字母,最大为Z

//暴力递归法
public static int convertToStringOne(String str){
    //边界判断
    if(str == null || str.length() == 0){
        return 0;
    }

    //字符串转化为数组
    char[] chars = str.toCharArray();
    int result = convertOne(chars, 0);
    return result;
}

public static int convertOne(char[] chars, int index){
    //下标越界直接返回
    if(index == chars.length){
        return 1;
    }

    //O做开头是无效解,直接返回
    if(chars[index] == '0'){
        return 0;
    }

    //一个字符转的情况
    int ans1 = convertOne(chars, index + 1);
    int ans2 = ans1;
    //两个字符转的情况,第一个字符不大于2,第二个字符不超过7,只有26个字符
    if(index + 1 < chars.length &&  (chars[index] - '0')*10 + (chars[index + 1] - '0') < 27){
        ans2 += convertOne(chars, index + 2);
    }
    return ans2;
}

思路二:傻缓存

用数组存已经计算的结果。

//傻缓存法
public static int convertToStringTwo(String str){
    //边界判断
    if(str == null || str.length() == 0){
        return 0;
    }

    //字符串转化为数组
    char[] chars = str.toCharArray();

    int N = chars.length;
    //缓存数组
    int[] dp = new int[N];

    int result = convertTwo(chars, 0, dp);
    return result;
}

public static int convertTwo(char[] chars, int index, int[] dp){
    //下标越界直接返回
    if(index == chars.length){
        return 1;
    }

    if(dp[index] != 0){
        return dp[index];
    }

    //O做开头是无效解,直接返回
    if(chars[index] == '0'){
        return 0;
    }

    //一个字符转的情况
    int ans1 = convertOne(chars, index + 1);
    int ans2 = ans1;
    //两个字符转的情况,第一个字符不大于2,第二个字符不超过7,只有26个字符
    if(index + 1 < chars.length &&  (chars[index] - '0')*10 + (chars[index + 1] - '0') < 27){
        ans2 += convertOne(chars, index + 2);
    }
    dp[index] = ans2;
    return ans2;
}

思路三:动态规划按规律直接写值

public static int convertToStringThree(String str){
    //边界判断
    if(str == null || str.length() == 0){
        return 0;
    }

    //字符串转化为数组
    char[] chars = str.toCharArray();

    int N = chars.length;
    //缓存数组
    int[] dp = new int[N+1];
    //最后一个的情况 相当于 判断:
    // if(index == chars.length){
    //     return 1;
    // }
    dp[N] = 1;
    //填结果
    for (int i = N - 1; i >= 0; i--) {
        //0 - N-1要判断'0'的情况
        if(chars[i] != '0'){
            int result = dp[i + 1];
            if(i + 1 < chars.length && (chars[i] - '0')*10 + (chars[i + 1] - '0') < 27){
                result += dp[i+2];
            }
            dp[i] = result;
        }
    }

    return dp[0];
}

总结测试

public class ConvertToLetterString {

    //暴力递归法
    public static int convertToStringOne(String str){
        //边界判断
        if(str == null || str.length() == 0){
            return 0;
        }

        //字符串转化为数组
        char[] chars = str.toCharArray();
        int result = convertOne(chars, 0);
        return result;
    }

    public static int convertOne(char[] chars, int index){
        //下标越界直接返回
        if(index == chars.length){
            return 1;
        }

        //O做开头是无效解,直接返回
        if(chars[index] == '0'){
            return 0;
        }

        //一个字符转的情况
        int ans1 = convertOne(chars, index + 1);
        int ans2 = ans1;
        //两个字符转的情况,第一个字符不大于2,第二个字符不超过7,只有26个字符
        if(index + 1 < chars.length &&  (chars[index] - '0')*10 + (chars[index + 1] - '0') < 27){
            ans2 += convertOne(chars, index + 2);
        }
        return ans2;
    }

    //傻缓存法
    public static int convertToStringTwo(String str){
        //边界判断
        if(str == null || str.length() == 0){
            return 0;
        }

        //字符串转化为数组
        char[] chars = str.toCharArray();

        int N = chars.length;
        //缓存数组
        int[] dp = new int[N];

        int result = convertTwo(chars, 0, dp);
        return result;
    }

    public static int convertTwo(char[] chars, int index, int[] dp){
        //下标越界直接返回
        if(index == chars.length){
            return 1;
        }

        if(dp[index] != 0){
            return dp[index];
        }

        //O做开头是无效解,直接返回
        if(chars[index] == '0'){
            return 0;
        }

        //一个字符转的情况
        int ans1 = convertOne(chars, index + 1);
        int ans2 = ans1;
        //两个字符转的情况,第一个字符不大于2,第二个字符不超过7,只有26个字符
        if(index + 1 < chars.length &&  (chars[index] - '0')*10 + (chars[index + 1] - '0') < 27){
            ans2 += convertOne(chars, index + 2);
        }
        dp[index] = ans2;
        return ans2;
    }

    public static int convertToStringThree(String str){
        //边界判断
        if(str == null || str.length() == 0){
            return 0;
        }

        //字符串转化为数组
        char[] chars = str.toCharArray();

        int N = chars.length;
        //缓存数组
        int[] dp = new int[N+1];
        //最后一个的情况 相当于 判断:
        // if(index == chars.length){
        //     return 1;
        // }
        dp[N] = 1;
        //填结果
        for (int i = N - 1; i >= 0; i--) {
            //0 - N-1要判断'0'的情况
            if(chars[i] != '0'){
                int result = dp[i + 1];
                if(i + 1 < chars.length && (chars[i] - '0')*10 + (chars[i + 1] - '0') < 27){
                    result += dp[i+2];
                }
                dp[i] = result;
            }
        }

        return dp[0];
    }

    public static String generateStr(int maxSize){

        char[] chars = new char[maxSize];

        for (int i = 0; i < maxSize; i++) {
            int digital = (int)(10 * Math.random());
            chars[i] = (char) (digital + '0');
        }

        return chars.toString();
    }


    public static void main(String[] args) {

        System.out.println("测试开始:");
        for (int i = 0; i < 10000; i++) {
            //随机生成字符串的大小
            int maxSize = (int)(101 * Math.random());
            String str = generateStr(maxSize);

            int resultOne = convertToStringOne(str);
            int resultTwo = convertToStringTwo(str);
            int resultThree = convertToStringThree(str);
            if(resultOne != resultTwo || resultOne != resultThree || resultTwo != resultThree){
                System.out.println("不行,小伙子,再看看!!");
            }
        }
        System.out.println("测试结束");

    }


}

举报

相关推荐

0 条评论