LeetCode 91. Decode Ways
Solution1:我的答案
还是记录一下,最容易想到的是DFS,但是在第223/238个case上就超时了。。。
class Solution {
public:
int numDecodings(string s) { //先来一波DFS
int res = 0, start = 0;
my_numDecodings(s, res, start);
return res;
}
void my_numDecodings(string& s, int& res, int start) {
if (start == s.size()) {
res++;
return;
} else {
if (s[start] == '0')
return; //如果当前数字字符串的起始位置为'0',直接return
for (int i = start; i < s.size(); i++) {
string temp = s.substr(start, i - start + 1);
if (atoi(temp.c_str()) < 1 || atoi(temp.c_str()) > 26)
continue;
else {
my_numDecodings(s, res, i + 1);
}
}
}
}
};
Solution2:
记忆化递归,参考链接:https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-91-decode-ways/
Time complexity:
O(n2)
O
(
n
2
)
Space complexity:
O(n2)
O
(
n
2
)
这种拷贝子串的方式更符合人类思维
// Author: Huahua
// Runtime: 6 ms
class Solution {
public:
int numDecodings(string s) {
if(s.length() == 0) return 0;
m_ways[""] = 1;
return ways(s);
}
private:
int ways(const string& s) {
if (m_ways.count(s)) return m_ways[s];
if (s[0] == '0') return 0;
if (s.length() == 1) return 1;
int w = ways(s.substr(1));
const int prefix = stoi(s.substr(0, 2));
if (prefix <= 26)
w += ways(s.substr(2));
m_ways[s] = w;
return w;
}
unordered_map<string, int> m_ways;
};
优化版记忆化递归
Time complexity:
O(n)
O
(
n
)
Space complexity:
O(n)
O
(
n
)
// Author: Huahua
// Runtime: 3 ms
class Solution {
public:
int numDecodings(string s) {
if(s.length() == 0) return 0;
return ways(s, 0, s.length() - 1);
}
private:
int ways(const string& s, int l, int r) {
if (m_ways.count(l)) return m_ways[l];
if (s[l] == '0') return 0;
if (l >= r) return 1; // Single digit or empty.
int w = ways(s, l + 1, r);
const int prefix = (s[l] - '0') * 10 + (s[l + 1] - '0');
if (prefix <= 26)
w += ways(s, l + 2, r);
m_ways[l] = w;
return w;
}
// Use l as key.
unordered_map<int, int> m_ways;
};
Solution3:
DP,参考链接:https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-91-decode-ways/
Time complexity:
O(n)
O
(
n
)
Space complexity:
O(1)
O
(
1
)
class Solution {
public:
int numDecodings(string s) {
if (s.empty() || s[0] == '0') return 0;
if (s.length() == 1) return 1;
const int n = s.length();
int w1 = 1;
int w2 = 1;
for (int i = 1; i < n; ++i) {
int w = 0;
if (!isValid(s[i]) && !isValid(s[i - 1], s[i])) return 0;
if (isValid(s[i])) w = w1;
if (isValid(s[i - 1], s[i])) w += w2;
w2 = w1;//w -> dp[i]; w1 -> dp[i-1]; w2 -> dp[i-2]
w1 = w;
}
return w1;
}
private:
bool isValid(const char c) { return c != '0'; }
bool isValid(const char c1, const char c2) {
const int num = (c1 - '0')*10 + (c2 - '0');
return num >= 10 && num <= 26;
}
};