解码方法~

一条包含字母A - Z的消息通过以下映射进行了编码
‘A’ -> 1
‘B’ -> 2

‘Z’ -> 26

给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。

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

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

思路:动态规划

用vector< int > dp数组来表示前i个数字解码的方式数。

记当前第 i 位的数字为 ai,第i-1位数字为 ai-1
则有如下转移方程:
在这里插入图片描述

class Solution {
public:
	bool check(string s) {
		if (s[0] == '0') return false;
		int n = stoi(s);
		return (n <= 26 && n >= 1);
	}
	int numDecodings(string s) {
		int n = s.length();
		int i;
		if (s[0] == '0') return 0;
		vector<int> dp(n+1, 1);
		for(i = 2; i <= n; i++)
		{
			bool flag1 = check(s.substr(i-2, 2));
			bool flag2 = check(s.substr(i-1, 1));
			if (flag1 && flag2) dp[i] = dp[i-2] + dp[i-1];
			else if (flag1) dp[i] = dp[i-2];
			else if (flag2) dp[i] = dp[i-1];
			else return 0;
		}
		return dp[n];
	}
};

可以简化,令空间复杂度为O(1)

  • dp[i]为str[0…i]的编码方法总数
  • 分情况:
    • 若s[i] = ‘0’,那么若s[i - 1] = ‘1’ or ‘2’,则dp[i] = dp[i - 2];否则return 0
      • 解释:由于0无法单独映射字母,必须跟s[i - 1]组合,s[i - 1] + s[i]唯一,则dp[i] = dp[i - 2] 不增加情况。
    • 若s[i - 1] = ‘1’,则dp[i] = dp[i - 1] + dp[i - 2]
      • 解释,如果s[i - 1]与s[i]分开编码,则为dp[i - 1];如果合并编码,同上述情况,则为dp[i - 2]
    • 若s[i - 1] = ‘2’,并且 ‘1’ <= s[i] <= ‘6’,则dp[i] = dp[i - 1] + dp[i - 2]
      • 解释,由于s[i - 1] = ‘2’,并且’1’ <= s[i] <= ‘6’,则也是可以分两种情况进行编码。
    • 除此之外的其他情况,
  • 由上述分析可知,dp[i]仅可能与前两项有关,因此可以用单变量代替dp[]数组,将空间复杂度从O(n)降到O(1)
int numDecodings(string s) {
    if (s[0] == '0') return 0;
    int pre = 1, curr = 1;//dp[-1] = dp[0] = 1
    for (int i = 1; i < s.size(); i++) {
        int tmp = curr;
        if (s[i] == '0')
            if (s[i - 1] == '1' || s[i - 1] == '2') curr = pre;
            else return 0;
        else if (s[i - 1] == '1' || (s[i - 1] == '2' && s[i] >= '1' && s[i] <= '6'))
            curr = curr + pre;
        pre = tmp;
    }
    return curr;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值