Skip to content

Commit 3afbd3c

Browse files
authored
Create problem7
1 parent 24a95c9 commit 3afbd3c

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

daily_coding_problems/problem7

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
Daily Coding Problem #7
2+
Problem
3+
This problem was asked by Facebook.
4+
5+
Given the mapping a = 1, b = 2, ... z = 26, and an encoded message, count the number of ways it can be decoded.
6+
7+
For example, the message '111' would give 3, since it could be decoded as 'aaa', 'ka', and 'ak'.
8+
9+
You can assume that the messages are decodable. For example, '001' is not allowed.
10+
11+
Solution
12+
This looks like a problem that is ripe for solving with recursion. First, let's try to think of a recurrence we can use for this problem. We can try some cases:
13+
14+
"", the empty string and our base case, should return 1.
15+
"1" should return 1, since we can parse it as "a" + "".
16+
"11" should return 2, since we can parse it as "a" + "a" + "" and "k" + "".
17+
"111" should return 3, since we can parse it as:
18+
"a" + "k" + ""
19+
"k" + "a" + ""
20+
"a" + "a" + "a" + "".
21+
"011" should return 0, since no letter starts with 0 in our mapping.
22+
"602" should also return 0 for similar reasons.
23+
We have a good starting point. We can see that the recursive structure is as follows:
24+
25+
If string starts with zero, then there's no valid encoding.
26+
If the string's length is less than or equal to 1, there is only 1 encoding.
27+
If the first two digits form a number k that is less than or equal to 26, we can recursively count the number of encodings assuming we pick k as a letter.
28+
We can also pick the first digit as a letter and count the number of encodings with this assumption.
29+
def num_encodings(s):
30+
if s.startswith('0'):
31+
return 0
32+
elif len(s) <= 1: # This covers empty string
33+
return 1
34+
35+
total = 0
36+
37+
if int(s[:2]) <= 26:
38+
total += num_encodings(s[2:])
39+
40+
total += num_encodings(s[1:])
41+
return total
42+
However, this solution is not very efficient. Every branch calls itself recursively twice, so our runtime is O(2n). We can do better by using dynamic programming.
43+
44+
All the following code does is repeat the same computation as above except starting from the base case and building up the solution. Since each iteration takes O(1), the whole algorithm now takes O(n).
45+
46+
from collections import defaultdict
47+
48+
def num_encodings(s):
49+
# On lookup, this hashmap returns a default value of 0 if the key doesn't exist
50+
# cache[i] gives us # of ways to encode the substring s[i:]
51+
cache = defaultdict(int)
52+
cache[len(s)] = 1 # Empty string is 1 valid encoding
53+
54+
for i in reversed(range(len(s))):
55+
if s[i].startswith('0'):
56+
cache[i] = 0
57+
elif i == len(s) - 1:
58+
cache[i] = 1
59+
else:
60+
if int(s[i:i + 2]) <= 26:
61+
cache[i] = cache[i + 2]
62+
cache[i] += cache[i + 1]
63+
return cache[0]

0 commit comments

Comments
 (0)