Decode Ways 解码方法

一条包含字母 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) 。

思路:

这道题目不复杂,主要是根据test case来看有很多特殊的情况需要我们进行处理,这里先说明解题思路,首先我们申请一个一维数组dp,长度为s长度+1,并把dp[0]设置为1。于是dp的下标便从1开始,对应s的第一个数即s[0]。把情况分为几种情况:

分为以下几个区间:

(1)X0:res[i]=0(X是不等于1和2的数,无法解析,没有可行解析方式);
(2)10, 20:res[i]=res[i-2](只有第二种情况成立);
(3)11-19, 21-26:res[i]=res[i-1]+res[i-2](两种情况都可行);
(4)01-09, 27-99:res[i]=res[i-1](只有第一种情况可行);

看着很乱,先看递归公式(后面有解释)为:

		dp[i] = s[i - 1] == '0' ? 0 : dp[i - 1];
		if (i > 1 && (s[i-2]=='1' || (s[i-2]=='2' && s[i-1]<='6'))) {
			dp[i] += dp[i - 2];
		}

这个递推公式很巧,通过s[i-1]是否为0把情况延展到s[i-2]的情况,非常巧妙。

总结如下:

1:如果s[i-1]为0,那么先把dp[i]赋值为0,然后进一步看前一位即s[i-2],如果s[i-2]是有效的,即10或者20,那么总的递推式就是:dp[i]=dp[i-2]

2:如果s[i-1]为0,如果s[i-2]是无效的,即在(10~19,20~26)范围之外,那么总的递推式就是:dp[i]=0

3:如果s[i-1]不为0,且s[i-2]是无效的,那么递推式是dp[i]=dp[i-1]

4:如果s[i-1]不为0,且s[i-2]是有效的,那么递推式是dp[i]=dp[i-2]+dp[i-1]

一共四个递推式包含在两个公式中,非常巧妙。

参考代码:

    int numDecodings(string s) {
	if (s.size() == 0 || s.size()==1 && s[0]=='0') {
		return 0;
	}
	int res = 0;
	int *dp = new int[s.size() + 1];
	dp[0] = 1;
	for (int i = 1; i <= s.size(); i++) {
		dp[i] = s[i - 1] == '0' ? 0 : dp[i - 1];
		if (i > 1 && (s[i-2]=='1' || (s[i-2]=='2' && s[i-1]<='6'))) {
			dp[i] += dp[i - 2];
		}
	}
	res = dp[s.size()];
	delete[] dp;
	return res;
    }



猜你喜欢

转载自blog.csdn.net/qq_26410101/article/details/80738750