leetcode91. 解码方法

解码方法

一条包含字母 A-Z 的消息通过以下方式进行了编码:

‘A’ -> 1
‘B’ -> 2

‘Z’ -> 26

给定一个只包含数字的非空字符串,请计算解码方法的总数。

示例 1:

输入: “12”
输出: 2
解释: 它可以解码为 “AB”(1 2)或者 “L”(12)。

示例 2:

输入: “226”
输出: 3
解释: 它可以解码为 “BZ” (2 26), “VF” (22 6), 或者 “BBF” (2 2 6) 。

思路

1.递归回溯
2.费波纳希

目前均超时,需要优化,参考爬楼梯

3.参考爬楼梯,非递归费波纳希,从下到上,保存中间变量
4.dp

实现

class Solution {
public:
    int numDecodings(string s) {
        int len = s.size();
        vector<int> dp(1 + len);
        dp[0] = 1;
        if (s[0] == '0') {
            return 0;
        }
        dp[1] = 1;
        for (int i = 2; i <= len; ++i) {
            if (s[i - 1] == '0') {
                if (s[i - 2] > '0' && s[i - 2] < '3') {
                    dp[i] = dp[i - 2];
                } else {
                    return 0;
                }
            } else {
                dp[i] = dp[i - 1];
                if (s[i - 2] == '2' && s[i - 1] <= '6'
                    || s[i - 2] == '1') {
                    dp[i] += dp[i - 2];
                }
            }
        }
        for (auto ele : dp) {
            cout << ele << endl;
        }
        return dp[len];
    }
};

递归回溯

class Solution {
public:
    int numDecodings(string s) {
        int res = 0;
        func(res, s, 0);
        return res;
        
    }
    void func(int &res, string s, int start) {
        if (start > s.size()) {
            return;
        }
        if (start == s.size() - 2) {
            if (s[start] == '1' || (s[start] == '2' && s[s.size() - 1] <= '6')) {
                res++;
            }
        }
        if (start == s.size() - 1 && s[s.size() - 1] != '0') {
            res++;
        }
        if (start < s.size()) {
            if (s[start] == '0') {
                    return;
            }
            func(res, s, start + 1);
            if (start + 1 < s.size()) {
                if (s[start] < '2' || (s[start] == '2' && s[start + 1] <= '6')) {
                    func(res, s, start + 2);
                }
            }
        }
    }
};

费波纳希

class Solution {
public:
    int numDecodings(string s) {
      if (s.size() == 1) {
          if (s == "0") {
              return 0;
          } else {
              return 1;
          }
      } 
      
    if (s.size() == 2) {
        if (s[0] == '1') {
             if (s[1] != '0') {
                return 2;
            } else {
                return 1;
            }
        }
        if (s[0] == '2') {
            if (s[1] == '0') {
                return 1;
            } else if (s[1] < '7') {
                return 2;
            } else {
                return 1;
            }
        }
        if (s[0] > '2') {
            if (s[1] == '0') {
                return 0;
            } else {
                return 1;
            }
        }

         
     } 
      if (s[0] == '0') {
          return 0;
      }
      
      if (s[0] == '1' || (s[0] == '2' && s[1] < '7')) {
          return numDecodings(s.substr(1, s.size() - 1)) + numDecodings(s.substr(2, s.size() - 2));
      }  
      return numDecodings(s.substr(1, s.size() - 1));
    }
};

较好的解法:非递归费波纳希

class Solution {
public:
    int numDecodings(string s) {
                int len = s.size();
        if (len == 0 || s[0] == '0') {
            return 0;
        }
        if (len == 1) {
            return 1;
        } 
        int a = 1;
        int b = 1;
  
        long res = 0;
        for (int i = 2; i <= len; i++) {
            res = 0;
            if (s[i - 1] != '0') {
                res = b;
            }
            if (s[i - 2] == '1' || (s[i - 2] == '2' && s[i - 1] < '7')) {
                res = res + a;
            }
             a = b;
             b = res;
        }
        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值