23. Total Decoding Messages

The problem can be found at the following link: Question Link

Problem Description

A message containing letters A-Z is encoded using the following mapping:

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

Given a numeric string digits, return the total number of ways the message can be decoded.

Examples

Example 1:

Input:

digits = "123"

Output:

3

Explanation:

"123" can be decoded as:

  • "ABC" (1, 2, 3)

  • "LC" (12, 3)

  • "AW" (1, 23)

Example 2:

Input:

Output:

Explanation:

"90" is not a valid encoding because '0' cannot be decoded.

Example 3:

Input:

Output:

Explanation:

"05" is not valid because leading zero makes it an invalid encoding.

Constraints:

  • $(1 \leq \text{digits.length} \leq 10^3)$

My Approach:

Optimized Space Dynamic Programming

Algorithm Steps:

  1. Edge Case Handling: If digits[0] == '0', return 0 because it cannot be decoded.

  2. Use Two Variables (prev2 and prev1):

    • prev1: Stores the number of ways to decode up to index i-1.

    • prev2: Stores the number of ways to decode up to index i-2.

  3. Iterate Over the String:

    • If digits[i] is not '0', add prev1 to the current count.

    • If digits[i-1]digits[i] forms a valid number (10-26), add prev2.

  4. Update prev2 and prev1 for the next iteration.

Time and Auxiliary Space Complexity

  • Expected Time Complexity: O(N), as we iterate through the string once.

  • Expected Auxiliary Space Complexity: O(1), since we use only two variables.

Code (C++)

πŸ›  Alternative Solutions

2️⃣ Dynamic Programming with Array (O(N) Time, O(N) Space)

Approach:

  • Instead of using two variables (prev1, prev2), we maintain a DP array dp[i], where dp[i] stores the number of ways to decode the string up to index i.

  • Transition:

    • If s[i] is not '0', add dp[i-1] to dp[i].

    • If s[i-1]s[i] forms a valid two-digit number, add dp[i-2] to dp[i].

  • Return dp[n].

3️⃣ Memoization (Top-Down DP, O(N) Time, O(N) Space)

Approach:

  • Instead of iterative DP, use recursion with memoization to store results.

  • Define countWays(i) as the number of ways to decode s[i:].

  • Base case: If i == n, return 1.

  • If s[i] is '0', return 0 (invalid).

  • Recursive cases:

    • Decode s[i] alone (countWays(i+1)).

    • Decode s[i]s[i+1] if valid (countWays(i+2)).

Comparison of Approaches

Approach

⏱️ Time Complexity

πŸ—‚οΈ Space Complexity

βœ… Pros

⚠️ Cons

Optimized DP (Two Variables)

🟑 O(N)

🟒 O(1)

Space efficient, fast

Harder to understand

DP with Array

🟑 O(N)

🟑 O(N)

Easier to implement

Extra space for dp array

Memoization (Top-Down DP)

🟑 O(N)

πŸ”΄ O(N)

Good for recursion lovers

Higher memory consumption

πŸ’‘ Best Choice?

  • βœ… Optimized DP (O(1) Space) is the best due to minimal space usage.

  • βœ… DP with Array is useful for educational purposes, but not space efficient.

  • βœ… Memoization is useful if you prefer recursion.

Code (Java)

Code (Python)

🎯 Contribution and Support:

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: Any Questions. Let’s make this learning journey more collaborative!

⭐ If you find this helpful, please give this repository a star! ⭐


πŸ“ Visitor Count

Last updated