Leet Code OJ 91. Decode Ways [Difficulty: Medium]

题目:

A message containing letters from A-Z is being encoded to numbers using the following mapping:

‘A‘ -> 1
‘B‘ -> 2
...
‘Z‘ -> 26

Given an encoded message containing digits, determine the total number of ways to decode it.

For example,

Given encoded message “12”, it could be decoded as “AB” (1 2) or “L” (12).

The number of ways decoding “12” is 2.

翻译:

一条消息有A-Z这些字母组成,但是消息被编码为数字了,按照以下方式:

‘A‘ -> 1
‘B‘ -> 2
...
‘Z‘ -> 26

给你一条编码后的消息,算出可能的解码方式的数量。

例如,给你一个消息”12”,它可以被解析为“AB”(1,2)或者“L”(12),所以这条消息解码方式的数量是2。

分析:

以下有2种方式可以实现,其中方式一在LeetCode的耗时是8 ms,方式二的是 2 ms。

方式一:假设字符串无限长,例如ABXXXXXXX…,我们只关注前2位。

1. 当A单独解析时,可能的解析方式有numDecodings(BXXXXXXX…)种。

2. 当A和B组合解析时,可能的解析方式有numDecodings(XXXXXXX…)种。

最后的结果,是上述2种情况的和。

方式二:

1. 首先将字符串中的数字进行校验、转换整理。我们将数字分为4类:

1)拆也可以不拆也可以,但不能打头,例如18的8、26的6,用Y替换

2)必须拆,并且不能打头,例如28的8,直接用X替换

3)拆也可以不拆也可以,但可以打头,例如11的1,不修改

4)必须与前一个数字合并,例如10的0,将前一个数字和本数字替换为XX

上述X表示隔断,即X前后的数字分开计算,再乘起来

上述Y表示隔断,与X类似,但是Y参与前面的数字计算。

2. 经过步骤一,字符串中的字符只剩下1、2、X、Y了。其中X、Y作为隔断,只要统计被隔断分割开来的每组数字的结果,然后把它们相乘起来即可。而如何计算每组数字的结果,通过观察发现,每组数字的结果与输入数字的个数有关,并且符合斐波那契数列。

Java版代码(方式1):

public class Solution091A {
    private static Map<String, Integer> resMap = new HashMap<>();

    public int numDecodings(String s) {
        char[] chars = s.toCharArray();
        int len = chars.length;
        if (len == 0) return 0;
        Integer res1 = 0;
        Integer res2 = 0;
        if (len >= 1) {
            char ch = chars[0];
            if (ch == ‘0‘) {
                return 0;
            } else {
                if (len == 1) {
                    res1 = 1;
                } else {
                    String substring = s.substring(1);
                    res1 = resMap.get(substring);
                    if (res1 == null) {
                        res1 = numDecodings(substring);
                        resMap.put(substring, res1);
                    }
                }
            }
            if (len >= 2) {
                if (ch == ‘1‘) {
                    if (len == 2) {
                        res2 = 1;
                    } else {
                        res2 = numDecodings(s.substring(2));
                    }
                } else if (ch == ‘2‘) {
                    if (chars[1] >= ‘0‘ && chars[1] <= ‘6‘) {
                        if (len == 2) {
                            res2 = 1;
                        } else {
                            String substring = s.substring(2);
                            res2 = resMap.get(substring);
                            if (res2 == null) {
                                res2 = numDecodings(substring);
                                resMap.put(substring, res2);
                            }
                        }
                    }
                }
            }
        }
        return res1 + res2;
    }
}

Java版代码(方式2):

public class Solution091B {
private static Map<Integer, Integer> fMap = new HashMap<>();

    public int numDecodings(String input) {
        if (input == null || input.length() == 0) {
            return 0;
        }
        char[] chars = input.toCharArray();
        if (!clean(chars)) return 0;
        return cal(chars);
    }

    /**
     * 将字符串中的数字进行校验、转换整理
     *
     * @param chars
     * @return 校验结果是否合法
     * @author lnho
     */
    private boolean clean(char[] chars) {
        for (int i = 0; i < chars.length; i++) {
            char current = chars[i];
            if (current == ‘0‘ || (current >= ‘3‘ && current <= ‘9‘)) {
                if (i == 0) {
                    if (current == ‘0‘) {
                        return false;
                    } else {
                        //为第一位数字,符合情况(2)
                        chars[i] = ‘X‘;
                        continue;
                    }
                }
                char previous = chars[i - 1];
                if (previous != ‘1‘ && previous != ‘2‘) {
                    if (current == ‘0‘) {
                        return false;
                    } else {
                        //前面为隔断(X,Y),符合情况(2)
                        chars[i] = ‘X‘;
                        continue;
                    }
                }

                if (previous == ‘2‘ && current > ‘6‘) {
                    //符合情况(2)
                    chars[i] = ‘X‘;
                    continue;
                }
                if (current == ‘0‘) {
                    //符合情况(4)
                    chars[i - 1] = ‘X‘;
                    chars[i] = ‘X‘;
                } else {
                    //符合情况(1)
                    chars[i] = ‘Y‘;
                }
            }
            //符合情况(3)
        }
        return true;
    }

    /**
     * 计算结果
     *
     * @param chars 经过上一个步骤,入参的字符数组中只包括1,2,X,Y了
     * @return
     * @author lnho
     */
    private int cal(char[] chars) {
        int count = 0;
        int sum = 1;
        for (char current : chars) {
            if (current == ‘1‘ || current == ‘2‘) {
                count++;
            } else if (current == ‘Y‘) {
                sum *= fibonacci(count + 1);
                count = 0;
            } else {
                if (count != 0) {
                    sum *= fibonacci(count);
                    count = 0;
                }
            }
        }
        if (count != 0) {
            sum *= fibonacci(count);
        }
        return sum;
    }

    /**
     * 获取斐波那契数值
     *
     * @param n
     * @return
     * @author lnho
     */
    private int fibonacci(int n) {
        if (n == 1 || n == 2) {
            return n;
        }
        Integer fn = fMap.get(n);
        if (fn == null) {
            fn = fibonacci(n - 1) + fibonacci(n - 2);
            fMap.put(n, fn);
        }
        return fn;
    }
}
时间: 2024-10-12 11:05:50

Leet Code OJ 91. Decode Ways [Difficulty: Medium]的相关文章

Leet Code OJ 338. Counting Bits [Difficulty: Medium]

题目: Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array. Example: For num = 5 you should return [0,1,1,2,1,2]. Follow up: It is v

Leet Code OJ 189. Rotate Array [Difficulty: Easy]

题目: Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4]. Note: Try to come up as many solutions as you can, there are at least 3 different ways to solve thi

Leet Code OJ 338. Counting Bits [Difficulty: Easy]

题目: Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array. Example: For num = 5 you should return [0,1,1,2,1,2]. Follow up: It is v

Leet Code OJ 66. Plus One [Difficulty: Easy]

题目: Given a non-negative number represented as an array of digits, plus one to the number. The digits are stored such that the most significant digit is at the head of the list. 翻译: 给定一个非负数,它是有数字的数组组成,把这个非负数+1. 这个非负数的存储方式,是把最高有效位数字放到列表的前面. 分析: 首先考虑的是

Leet Code OJ 1. Two Sum [Difficulty: Easy]

题目: Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution. Example: Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1]

Leet Code OJ 27. Remove Element [Difficulty: Easy]

题目: Given an array and a value, remove all instances of that value in place and return the new length. The order of elements can be changed. It doesn't matter what you leave beyond the new length. 翻译: 给定一个数组和一个值,在原地移除所有的这个值的实例,并且返回新的数组长度. 元素的顺序可以被改变.

Leet Code OJ 223. Rectangle Area [Difficulty: Easy]

题目: Find the total area covered by two rectilinear rectangles in a 2D plane. Each rectangle is defined by its bottom left corner and top right corner as shown in the figure. Assume that the total area is never beyond the maximum possible value of int

Leet Code OJ 344. Reverse String [Difficulty: Easy]

题目: Write a function that takes a string as input and returns the string reversed. Example: Given s = "hello", return "olleh". 翻译: 写一个函数,使用字符串作为输入,返回它反转后的结果. 例如,输入"hello",返回"olleh". 分析: 转为字符数组后,将第一个字符和最后一个字符对调,第二个字符

Leet Code OJ 28. Implement strStr() [Difficulty: Easy]

题目: Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. 翻译: 实现一个方法strStr().返回字符串needle第一次在字符串haystack出现的下标,如果needle不是haystack的一部分,就返回-1. 分析: 在文本中查找某个模式出现的位置的算法,称为字符串匹配算法.常用的方法有