Problem Statement (Asked By Facebook)
Given the mapping a = 1
, b = 2
, …, z = 26
, and an encoded message, count the number of possible ways to decode it.
For example, the message '111'
would give 3
, since it could be decoded as 'aaa'
, 'ka'
, and 'ak'
.
You can assume that the messages are valid. For instance, '001'
is not allowed.
Problem link: https://leetcode.com/problems/decode-ways/
Disclaimer: Try solving the problem on your own first! Use this solution only as a reference to learn and improve.
This problem is well-suited for a recursive approach. Let’s break it down by defining a recurrence to solve it. Here are some test cases to understand the logic:
""
) is the base case, and it should return 1 since there’s one way to decode it: doing nothing."1"
should return 1, as it can only be decoded as "a"
."11"
should return 2 since it can be decoded as "aa"
or "k"
."111"
should return 3: "a" + "k"
"k" + "a"
"a" + "a" + "a"
."011"
or "602"
should return 0 because no letter starts with 0.The recursive structure is as follows:
0
, there’s no valid decoding.Here’s the recursive solution:
Approach 1:
public class DecodeWays { public static int numEncodings(String s) { if (s.startsWith("0")) { return 0; } else if (s.length() <= 1) { return 1; } int total = 0; if (Integer.parseInt(s.substring(0, 2)) <= 26) { total += numEncodings(s.substring(2)); } total += numEncodings(s.substring(1)); return total; } public static void main(String[] args) { System.out.println(numEncodings("111")); // Output: 3 System.out.println(numEncodings("011")); // Output: 0 } }
Approach 2:
Instead of making redundant recursive calls, we can use a bottom-up dynamic programming approach. We calculate the number of ways to decode the string from the end to the beginning and store intermediate results in a cache.
import java.util.HashMap; import java.util.Map; public class DecodeWays { public static int numEncodings(String s) { if (s.isEmpty() || s.startsWith("0")) { return 0; } Map<Integer, Integer> cache = new HashMap<>(); cache.put(s.length(), 1); // Base case: empty string has 1 way to decode for (int i = s.length() - 1; i >= 0; i--) { if (s.charAt(i) == '0') { cache.put(i, 0); } else { cache.put(i, cache.get(i + 1)); if (i + 1 < s.length() && Integer.parseInt(s.substring(i, i + 2)) <= 26) { cache.put(i, cache.get(i) + cache.get(i + 2)); } } } return cache.get(0); } public static void main(String[] args) { System.out.println(numEncodings("111")); // Output: 3 System.out.println(numEncodings("011")); // Output: 0 System.out.println(numEncodings("226")); // Output: 3 } }
2. Dynamic Programming Approach:
cache
(map) to avoid recalculating.Time Complexity: O(n), where n is the length of the string.
Space Complexity: O(n) for the cache.
Did this solution help you understand the concept better? Let me know your thoughts in the comments below! Don’t forget to follow us on Instagram @coderz.py for more DSA tips and solutions to ace your coding interviews.
Find the length of the longest absolute path to a file within the abstracted file…
You manage an e-commerce website and need to keep track of the last N order…
You are given a stream of elements that is too large to fit into memory.…
The formula for the area of a circle is given by πr². Use the Monte…
Given an integer k and a string s, write a function to determine the length…
There is a staircase with N steps, and you can ascend either 1 step or…