Number of ways to decode a string
up vote
1
down vote
favorite
I'm working on problem 91 on Leetcode.com called "Decode Ways" and I've successfully managed to get a working recursive solution but it results in Time Limited Exceeded (TLE). I'm new to utilizing memoization and I've been unable to discover how to properly memoize my results at each recursive step and check if I've already solve the sub-problem.
Prompt:
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1 'B' -> 2 ... 'Z' -> 26
Given a non-empty string containing only digits, determine the total
number of ways to decode it.
Working Code (TLE):
public int NumDecodings(string s)
{
if (s == null || s.Length == 0) return 0;
// int dp = new int[s.Length + 1];
// for (int i = 0; i < dp.Length; ++i) dp[i] = -1;
// dp[0] = 1;
// dp[1] = Decode(s, 0, 1, dp) + Decode(s, 0, 2, dp);
int jump1 = Decode(s, 0, 1);
int jump2 = Decode(s, 0, 2);
return jump1 + jump2;
// return dp[1];
}
public int Decode(string s, int i, int len)
{
if (i + len - 1 >= s.Length)
return 0;
// if (dp[i] > -1)
// return dp[i];
int sub = Convert.ToInt32(s.Substring(i, len));
if (sub > 26 || sub < 1 || s.Substring(i, len)[0] == '0')
return 0;
else if (i + len - 1 == s.Length - 1 && sub < 27 && sub > 0)
return 1;
int jump1 = i + len - 1 + 1 < s.Length ? Decode(s, i + len, 1) : 0;
int jump2 = i + len - 1 + 2 < s.Length ? Decode(s, i + len, 2) : 0;
// dp[i] = jump1 + jump2;
return jump1 + jump2;
// return dp[i];
}
c# recursion dynamic-programming
add a comment |
up vote
1
down vote
favorite
I'm working on problem 91 on Leetcode.com called "Decode Ways" and I've successfully managed to get a working recursive solution but it results in Time Limited Exceeded (TLE). I'm new to utilizing memoization and I've been unable to discover how to properly memoize my results at each recursive step and check if I've already solve the sub-problem.
Prompt:
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1 'B' -> 2 ... 'Z' -> 26
Given a non-empty string containing only digits, determine the total
number of ways to decode it.
Working Code (TLE):
public int NumDecodings(string s)
{
if (s == null || s.Length == 0) return 0;
// int dp = new int[s.Length + 1];
// for (int i = 0; i < dp.Length; ++i) dp[i] = -1;
// dp[0] = 1;
// dp[1] = Decode(s, 0, 1, dp) + Decode(s, 0, 2, dp);
int jump1 = Decode(s, 0, 1);
int jump2 = Decode(s, 0, 2);
return jump1 + jump2;
// return dp[1];
}
public int Decode(string s, int i, int len)
{
if (i + len - 1 >= s.Length)
return 0;
// if (dp[i] > -1)
// return dp[i];
int sub = Convert.ToInt32(s.Substring(i, len));
if (sub > 26 || sub < 1 || s.Substring(i, len)[0] == '0')
return 0;
else if (i + len - 1 == s.Length - 1 && sub < 27 && sub > 0)
return 1;
int jump1 = i + len - 1 + 1 < s.Length ? Decode(s, i + len, 1) : 0;
int jump2 = i + len - 1 + 2 < s.Length ? Decode(s, i + len, 2) : 0;
// dp[i] = jump1 + jump2;
return jump1 + jump2;
// return dp[i];
}
c# recursion dynamic-programming
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I'm working on problem 91 on Leetcode.com called "Decode Ways" and I've successfully managed to get a working recursive solution but it results in Time Limited Exceeded (TLE). I'm new to utilizing memoization and I've been unable to discover how to properly memoize my results at each recursive step and check if I've already solve the sub-problem.
Prompt:
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1 'B' -> 2 ... 'Z' -> 26
Given a non-empty string containing only digits, determine the total
number of ways to decode it.
Working Code (TLE):
public int NumDecodings(string s)
{
if (s == null || s.Length == 0) return 0;
// int dp = new int[s.Length + 1];
// for (int i = 0; i < dp.Length; ++i) dp[i] = -1;
// dp[0] = 1;
// dp[1] = Decode(s, 0, 1, dp) + Decode(s, 0, 2, dp);
int jump1 = Decode(s, 0, 1);
int jump2 = Decode(s, 0, 2);
return jump1 + jump2;
// return dp[1];
}
public int Decode(string s, int i, int len)
{
if (i + len - 1 >= s.Length)
return 0;
// if (dp[i] > -1)
// return dp[i];
int sub = Convert.ToInt32(s.Substring(i, len));
if (sub > 26 || sub < 1 || s.Substring(i, len)[0] == '0')
return 0;
else if (i + len - 1 == s.Length - 1 && sub < 27 && sub > 0)
return 1;
int jump1 = i + len - 1 + 1 < s.Length ? Decode(s, i + len, 1) : 0;
int jump2 = i + len - 1 + 2 < s.Length ? Decode(s, i + len, 2) : 0;
// dp[i] = jump1 + jump2;
return jump1 + jump2;
// return dp[i];
}
c# recursion dynamic-programming
I'm working on problem 91 on Leetcode.com called "Decode Ways" and I've successfully managed to get a working recursive solution but it results in Time Limited Exceeded (TLE). I'm new to utilizing memoization and I've been unable to discover how to properly memoize my results at each recursive step and check if I've already solve the sub-problem.
Prompt:
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1 'B' -> 2 ... 'Z' -> 26
Given a non-empty string containing only digits, determine the total
number of ways to decode it.
Working Code (TLE):
public int NumDecodings(string s)
{
if (s == null || s.Length == 0) return 0;
// int dp = new int[s.Length + 1];
// for (int i = 0; i < dp.Length; ++i) dp[i] = -1;
// dp[0] = 1;
// dp[1] = Decode(s, 0, 1, dp) + Decode(s, 0, 2, dp);
int jump1 = Decode(s, 0, 1);
int jump2 = Decode(s, 0, 2);
return jump1 + jump2;
// return dp[1];
}
public int Decode(string s, int i, int len)
{
if (i + len - 1 >= s.Length)
return 0;
// if (dp[i] > -1)
// return dp[i];
int sub = Convert.ToInt32(s.Substring(i, len));
if (sub > 26 || sub < 1 || s.Substring(i, len)[0] == '0')
return 0;
else if (i + len - 1 == s.Length - 1 && sub < 27 && sub > 0)
return 1;
int jump1 = i + len - 1 + 1 < s.Length ? Decode(s, i + len, 1) : 0;
int jump2 = i + len - 1 + 2 < s.Length ? Decode(s, i + len, 2) : 0;
// dp[i] = jump1 + jump2;
return jump1 + jump2;
// return dp[i];
}
c# recursion dynamic-programming
c# recursion dynamic-programming
edited yesterday
Jamal♦
30.2k11115226
30.2k11115226
asked yesterday
springathing
336
336
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
2
down vote
Memoization
Looking into memoization is a good idea - in this case it allows you to achieve $O(n)$ runtime performance instead of $O(n^2)$. One way to add memoization is to create a wrapper method that takes the same arguments as Decode. This method first looks up the given arguments in a dictionary, and if they're present, it can return the memoized result. If not, it will call Decode and store its result in the dictionary before returning it.
However, I would recommend removing NumDecodings and rewriting Decode so it only takes a single string parameter. That will simplify memoization and make it a little more efficient. For example, "412123" and "512123" both have the same suffix ("12123"), but because the 'sub-calls' ("412123", 1, 1) and ("512123", 1, 1) use different arguments (and thus different memoization keys) you won't benefit from memoization across those different inputs.
Other notes
- Instead of passing the original input string and an offset and length, consider passing 'the rest of the string' instead.
Decodecan then callDecode(s.Substring(1))if the leading digit is a valid unit, andDecode(s.Substring(2))if the leading 2 digits are a valid unit. - There are various things in the current code that can be simplified:
if (i + len - 1 >= s.Length)toif (i + len > s.Length)
s.Substring(i, len)[0] == '0'tos[i] == '0'
else if (i + len - 1 == s.Length - 1toelse if (i + len == s.Length
jump1 = i + len - 1 + 1tojump1 = i + len
jump2 = i + len - 1 + 2tojump2 = i + len + 1
- Moving
s.Substring(i, len)[0] == '0'to anelse ifbranch allows you to remove thesub < 27 && sub > 0checks below. - Disabling code during development is normal, but it's a good idea to clean things up from time to time.
- I would rename
Decodeto something more descriptive likeValidDecodingsCount-Decodeimplies that it actually decodes the given input, which is not the case.jump1andjump2aren't very descriptive names either, but it's a bit difficult to come up with better names. Mayberest1Combinationsandrest2Combinations?
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
Memoization
Looking into memoization is a good idea - in this case it allows you to achieve $O(n)$ runtime performance instead of $O(n^2)$. One way to add memoization is to create a wrapper method that takes the same arguments as Decode. This method first looks up the given arguments in a dictionary, and if they're present, it can return the memoized result. If not, it will call Decode and store its result in the dictionary before returning it.
However, I would recommend removing NumDecodings and rewriting Decode so it only takes a single string parameter. That will simplify memoization and make it a little more efficient. For example, "412123" and "512123" both have the same suffix ("12123"), but because the 'sub-calls' ("412123", 1, 1) and ("512123", 1, 1) use different arguments (and thus different memoization keys) you won't benefit from memoization across those different inputs.
Other notes
- Instead of passing the original input string and an offset and length, consider passing 'the rest of the string' instead.
Decodecan then callDecode(s.Substring(1))if the leading digit is a valid unit, andDecode(s.Substring(2))if the leading 2 digits are a valid unit. - There are various things in the current code that can be simplified:
if (i + len - 1 >= s.Length)toif (i + len > s.Length)
s.Substring(i, len)[0] == '0'tos[i] == '0'
else if (i + len - 1 == s.Length - 1toelse if (i + len == s.Length
jump1 = i + len - 1 + 1tojump1 = i + len
jump2 = i + len - 1 + 2tojump2 = i + len + 1
- Moving
s.Substring(i, len)[0] == '0'to anelse ifbranch allows you to remove thesub < 27 && sub > 0checks below. - Disabling code during development is normal, but it's a good idea to clean things up from time to time.
- I would rename
Decodeto something more descriptive likeValidDecodingsCount-Decodeimplies that it actually decodes the given input, which is not the case.jump1andjump2aren't very descriptive names either, but it's a bit difficult to come up with better names. Mayberest1Combinationsandrest2Combinations?
add a comment |
up vote
2
down vote
Memoization
Looking into memoization is a good idea - in this case it allows you to achieve $O(n)$ runtime performance instead of $O(n^2)$. One way to add memoization is to create a wrapper method that takes the same arguments as Decode. This method first looks up the given arguments in a dictionary, and if they're present, it can return the memoized result. If not, it will call Decode and store its result in the dictionary before returning it.
However, I would recommend removing NumDecodings and rewriting Decode so it only takes a single string parameter. That will simplify memoization and make it a little more efficient. For example, "412123" and "512123" both have the same suffix ("12123"), but because the 'sub-calls' ("412123", 1, 1) and ("512123", 1, 1) use different arguments (and thus different memoization keys) you won't benefit from memoization across those different inputs.
Other notes
- Instead of passing the original input string and an offset and length, consider passing 'the rest of the string' instead.
Decodecan then callDecode(s.Substring(1))if the leading digit is a valid unit, andDecode(s.Substring(2))if the leading 2 digits are a valid unit. - There are various things in the current code that can be simplified:
if (i + len - 1 >= s.Length)toif (i + len > s.Length)
s.Substring(i, len)[0] == '0'tos[i] == '0'
else if (i + len - 1 == s.Length - 1toelse if (i + len == s.Length
jump1 = i + len - 1 + 1tojump1 = i + len
jump2 = i + len - 1 + 2tojump2 = i + len + 1
- Moving
s.Substring(i, len)[0] == '0'to anelse ifbranch allows you to remove thesub < 27 && sub > 0checks below. - Disabling code during development is normal, but it's a good idea to clean things up from time to time.
- I would rename
Decodeto something more descriptive likeValidDecodingsCount-Decodeimplies that it actually decodes the given input, which is not the case.jump1andjump2aren't very descriptive names either, but it's a bit difficult to come up with better names. Mayberest1Combinationsandrest2Combinations?
add a comment |
up vote
2
down vote
up vote
2
down vote
Memoization
Looking into memoization is a good idea - in this case it allows you to achieve $O(n)$ runtime performance instead of $O(n^2)$. One way to add memoization is to create a wrapper method that takes the same arguments as Decode. This method first looks up the given arguments in a dictionary, and if they're present, it can return the memoized result. If not, it will call Decode and store its result in the dictionary before returning it.
However, I would recommend removing NumDecodings and rewriting Decode so it only takes a single string parameter. That will simplify memoization and make it a little more efficient. For example, "412123" and "512123" both have the same suffix ("12123"), but because the 'sub-calls' ("412123", 1, 1) and ("512123", 1, 1) use different arguments (and thus different memoization keys) you won't benefit from memoization across those different inputs.
Other notes
- Instead of passing the original input string and an offset and length, consider passing 'the rest of the string' instead.
Decodecan then callDecode(s.Substring(1))if the leading digit is a valid unit, andDecode(s.Substring(2))if the leading 2 digits are a valid unit. - There are various things in the current code that can be simplified:
if (i + len - 1 >= s.Length)toif (i + len > s.Length)
s.Substring(i, len)[0] == '0'tos[i] == '0'
else if (i + len - 1 == s.Length - 1toelse if (i + len == s.Length
jump1 = i + len - 1 + 1tojump1 = i + len
jump2 = i + len - 1 + 2tojump2 = i + len + 1
- Moving
s.Substring(i, len)[0] == '0'to anelse ifbranch allows you to remove thesub < 27 && sub > 0checks below. - Disabling code during development is normal, but it's a good idea to clean things up from time to time.
- I would rename
Decodeto something more descriptive likeValidDecodingsCount-Decodeimplies that it actually decodes the given input, which is not the case.jump1andjump2aren't very descriptive names either, but it's a bit difficult to come up with better names. Mayberest1Combinationsandrest2Combinations?
Memoization
Looking into memoization is a good idea - in this case it allows you to achieve $O(n)$ runtime performance instead of $O(n^2)$. One way to add memoization is to create a wrapper method that takes the same arguments as Decode. This method first looks up the given arguments in a dictionary, and if they're present, it can return the memoized result. If not, it will call Decode and store its result in the dictionary before returning it.
However, I would recommend removing NumDecodings and rewriting Decode so it only takes a single string parameter. That will simplify memoization and make it a little more efficient. For example, "412123" and "512123" both have the same suffix ("12123"), but because the 'sub-calls' ("412123", 1, 1) and ("512123", 1, 1) use different arguments (and thus different memoization keys) you won't benefit from memoization across those different inputs.
Other notes
- Instead of passing the original input string and an offset and length, consider passing 'the rest of the string' instead.
Decodecan then callDecode(s.Substring(1))if the leading digit is a valid unit, andDecode(s.Substring(2))if the leading 2 digits are a valid unit. - There are various things in the current code that can be simplified:
if (i + len - 1 >= s.Length)toif (i + len > s.Length)
s.Substring(i, len)[0] == '0'tos[i] == '0'
else if (i + len - 1 == s.Length - 1toelse if (i + len == s.Length
jump1 = i + len - 1 + 1tojump1 = i + len
jump2 = i + len - 1 + 2tojump2 = i + len + 1
- Moving
s.Substring(i, len)[0] == '0'to anelse ifbranch allows you to remove thesub < 27 && sub > 0checks below. - Disabling code during development is normal, but it's a good idea to clean things up from time to time.
- I would rename
Decodeto something more descriptive likeValidDecodingsCount-Decodeimplies that it actually decodes the given input, which is not the case.jump1andjump2aren't very descriptive names either, but it's a bit difficult to come up with better names. Mayberest1Combinationsandrest2Combinations?
answered 2 hours ago
Pieter Witvoet
5,011724
5,011724
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208849%2fnumber-of-ways-to-decode-a-string%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown