91.Decode Ways


91. Decode Ways

  • You have intercepted a secret message encoded as a string of numbers. The message is decoded via the following mapping:

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

  • However, while decoding the message, you realize that there are many different ways you can decode the message because some codes are contained in other codes ("2" and "5" vs "25").

    For example, "11106" can be decoded into:

    • "AAJF" with the grouping (1, 1, 10, 6)
    • "KJF" with the grouping (11, 10, 6)
    • The grouping (1, 11, 06) is invalid because "06" is not a valid code (only "6" is valid).

    Note: there may be strings that are impossible to decode.

    Given a string s containing only digits, return the number of ways to decode it. If the entire string cannot be decoded in any valid way, return 0.

    The test cases are generated so that the answer fits in a 32-bit integer.

Example 1

Input: s = "12"

Output: 2

Explanation:

"12" could be decoded as "AB" (1 2) or "L" (12).

Example 2

Input: s = "226"

Output: 3

Explanation:

"226" could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).

Example 3

Input: s = "06"

Output: 0

Explanation:

"06" cannot be mapped to "F" because of the leading zero ("6" is different from "06"). In this case, the string is not a valid encoding, so return 0.

Method 1

【O(n) time | O(n) space】
package Leetcode.DynamicProgramming;

/**
 * @author zhengstars
 * @date 2024/09/21
 */
public class DecodeWays {
    /**
     * Calculates the number of ways to decode a string of digits.
     * @param s The input string containing digits.
     * @return The number of possible decodings.
     */
    public static int numDecodings(String s) {
        int n = s.length();
        // dp[i] represents the number of ways to decode the first i characters
        int[] dp = new int[n + 1];

        // Base case: empty string has one way to decode (do nothing)
        dp[0] = 1;

        // Iterate through each character in the string
        for (int i = 1; i <= n; i++) {
            // Check if single digit decoding is possible
            if (s.charAt(i - 1) != '0') {
                // If the current digit is not '0', it can be decoded alone
                // So we add the number of ways to decode the string up to the previous position
                dp[i] += dp[i - 1];
            }

            // Check if two-digit decoding is possible
            if (i > 1 && s.charAt(i - 2) != '0' && twoDigitNum(s, i) <= 26) {
                // If the last two digits form a valid number (10-26),
                // we add the number of ways to decode the string up to two positions back
                dp[i] += dp[i - 2];
            }
        }

        // Return the total number of ways to decode the entire string
        return dp[n];
    }

    /**
     * Converts two consecutive digits in the string to an integer.
     * @param s The input string.
     * @param i The current position (we look at i-2 and i-1).
     * @return The integer value of the two digits.
     */
    private static int twoDigitNum(String s, int i) {
        // Convert char to int by subtracting '0'
        // Multiply the tens digit by 10 and add the ones digit
        return (s.charAt(i - 2) - '0') * 10 + (s.charAt(i - 1) - '0');
    }

    /**
     * Main method to test the solution with various test cases.
     */
    public static void main(String[] args) {

        // Test cases
        String[] testCases = {
                "12",    // Expected output: 2 (AB (1 2) or L (12))
                "226",   // Expected output: 3 (BZ (2 26) or VF (22 6) or BBF (2 2 6))
                "0",     // Expected output: 0 (cannot be decoded)
                "06",    // Expected output: 0 (cannot be decoded)
                "10",    // Expected output: 1 (J (10))
                "27",    // Expected output: 1 (BG (2 7))
                "234",   // Expected output: 3 (BCD (2 3 4) or WD (23 4) or BW (2 34))
                "1111"   // Expected output: 5 (AAAA, KAA, AKA, AAK, KK)
        };

        for (String testCase : testCases) {
            int result = numDecodings(testCase);
            System.out.println("Input: \"" + testCase + "\", Output: " + result);
        }
    }
}




Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • 2379. Minimum Recolors to Get K Consecutive Black Blocks
  • 2471. Minimum Number of Operations to Sort a Binary Tree by Level
  • 1387. Sort Integers by The Power Value
  • 2090. K Radius Subarray Averages
  • 2545. Sort the Students by Their Kth Score