LeetCode #639 Decode Ways II 解碼方法 II 639 Decode Ways II 解碼方法 II

639 Decode Ways II 解碼方法 II

Description:
A message containing letters from A-Z can be encoded into numbers using the following mapping:

'A' -> "1"
'B' -> "2"
...
'Z' -> "26"

To decode an encoded message, all the digits must be grouped then mapped back into letters using the reverse of the mapping above (there may be multiple ways). For example, "11106" can be mapped into:

"AAJF" with the grouping (1 1 10 6)
"KJF" with the grouping (11 10 6)
Note that the grouping (1 11 06) is invalid because "06" cannot be mapped into 'F' since "6" is different from "06".

In addition to the mapping above, an encoded message may contain the '*' character, which can represent any digit from '1' to '9' ('0' is excluded). For example, the encoded message "1" may represent any of the encoded messages "11", "12", "13", "14", "15", "16", "17", "18", or "19". Decoding "1" is equivalent to decoding any of the encoded messages it can represent.

Given a string s containing digits and the '*' character, return the number of ways to decode it.

Since the answer may be very large, return it modulo 10^9 + 7.

Example:

Example 1:

Input: s = ""
Output: 9
Explanation: The encoded message can represent any of the encoded messages "1", "2", "3", "4", "5", "6", "7", "8", or "9".
Each of these can be decoded to the strings "A", "B", "C", "D", "E", "F", "G", "H", and "I" respectively.
Hence, there are a total of 9 ways to decode "
".

Example 2:

Input: s = "1"
Output: 18
Explanation: The encoded message can represent any of the encoded messages "11", "12", "13", "14", "15", "16", "17", "18", or "19".
Each of these encoded messages have 2 ways to be decoded (e.g. "11" can be decoded to "AA" or "K").
Hence, there are a total of 9 * 2 = 18 ways to decode "1
".

Example 3:

Input: s = "2"
Output: 15
Explanation: The encoded message can represent any of the encoded messages "21", "22", "23", "24", "25", "26", "27", "28", or "29".
"21", "22", "23", "24", "25", and "26" have 2 ways of being decoded, but "27", "28", and "29" only have 1 way.
Hence, there are a total of (6 * 2) + (3 * 1) = 12 + 3 = 15 ways to decode "2
".

Constraints:

1 <= s.length <= 10^5
s[i] is a digit or '*'.

題目描述:
一條包含字母 A-Z 的消息通過以下的方式進行了編碼:

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

除了上述的條件以外,現在加密字符串可以包含字符 '*'了,字符'*'可以被當做1到9當中的任意一個數字。

給定一條包含數字和字符'*'的加密信息,請確定解碼方法的總數。

同時,由於結果值可能會相當的大,所以你應當對10^9 + 7取模。(翻譯者標註:此處取模主要是爲了防止溢出)

示例 :

示例 1 :

輸入: "*"
輸出: 9
解釋: 加密的信息可以被解密爲: "A", "B", "C", "D", "E", "F", "G", "H", "I".

示例 2 :

輸入: "1"
輸出: 9 + 9 = 18(翻譯者標註:這裏1
可以分解爲1,* 或者當做1*來處理,所以結果是9+9=18)

說明:

輸入的字符串長度範圍是 [1, 10^5]。
輸入的字符串只會包含字符 '*' 和 數字'0' - '9'。

思路:

動態規劃
dp[i] 表示前 i 個字符能夠形成的解碼方法總數
dp[i] = dp[i - 1] * a + dp[i - 2] * b
其中 a = s[i] == '*' ? 9 : (s[i] != '0'), 表示當前的字符如果爲 , 有 9 種取法(1 - 9), 如果爲 0 則爲 0, 否則爲 1; b 則需要再往前看一位, 如果 s[i - 1] == '1', 則一定可以和當前位置組合, b = a + (a == 0), 如果 s[i - 1] == '2', 則要求當前位要麼是 '0'-'7', 要麼是 '' 才能組合, 其餘情況都爲 0
可以看出只需要常數個變量即可
時間複雜度 O(n), 空間複雜度 O(1)

代碼:
C++:

class Solution 
{
public:
    int numDecodings(string s) 
    {
        long result = s[0] == '*' ? 9 : (s[0] != '0'), pre = 1;
        for (int i = 1, n = s.size(), a = 0, b = 0, mod = 1e9 + 7; i < n; i++)
        {
            a = s[i] == '*' ? 9 : (s[i] != '0');
            switch (s[i - 1])
            {
                case '1':
                    b = a + (a == 0);
                    break;
                case '2':
                    b = s[i] == '*' ? 6 : s[i] < '7' ? 1 : 0;
                    break;
                case '*':
                    b = a + (a == 0) + (s[i] == '*' ? 6 : s[i] < '7' ? 1 : 0);
                    break;
                default:
                    b = 0;
            }
            pre = (result * a + pre * b) % mod;
            swap(result, pre);
        }
        return result;
    }
};

Java:

class Solution {
    public int numDecodings(String s) {
        long result = s.charAt(0) == '*' ? 9 : (s.charAt(0) == '0' ? 0 : 1), pre = 1, cur = 0;
        int n = s.length(), mod = 1000000007;
        for (int i = 1, a = 0, b = 0; i < n; i++) {
            a = s.charAt(i) == '*' ? 9 : (s.charAt(i) == '0' ? 0 : 1);
            switch (s.charAt(i - 1)) {
                case '1':
                    b = a + (a == 0 ? 1 : 0);
                    break;
                case '2':
                    b = (s.charAt(i) == '*' ? 6 : (s.charAt(i) < '7' ? 1 : 0));
                    break;
                case '*':
                    b = a + (a == 0 ? 1 : 0) + (s.charAt(i) == '*' ? 6 : (s.charAt(i) < '7' ? 1 : 0));
                    break;
                default:
                    b = 0;
            }
            cur = (result * a + pre * b) % mod;
            pre = result;
            result = cur;
        }
        return (int)result;
    }
}

Python:

class Solution:
    def numDecodings(self, s: str) -> int:
        result, pre = 9 if s[0] == '*' else s[0] != '0', 1
        for i in range(1, len(s)):
            a = 9 if s[i] == '*' else s[i] != '0'
            b = (a + (not a) if s[i - 1] == '1' or s[i - 1] == '*' else 0) + (6 if s[i] == '*' else 1 if s[i] < '7' else 0) * (s[i - 1] == '2' or s[i - 1] == '*')
            result, pre = a * result + b * pre, result
        return result % (10 ** 9 + 7)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章