【DFS + 记忆化递归 + DP】LeetCode 91. Decode Ways

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 ( n 2 )
Space complexity: 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 )
Space complexity: 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 )
Space complexity: 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;
    }
};

猜你喜欢

转载自blog.csdn.net/Allenlzcoder/article/details/81416716