【DP】LeetCode - Decode Ways I、II

LeetCode - 91. Decode Ways

A message containing letters from A-Z is being encoded to numbers using the following mapping:
‘A’ -> 1
‘B’ -> 2

‘Z’ -> 26
Given a non-empty string containing only digits, determine the total number of ways to decode it.

Input: “12” Output: 2
Explanation: It could be decoded as “AB” (1 2) or “L” (12).

Input: “226” Output: 3
Explanation: It could be decoded as “BZ” (2 26), “VF” (22 6), or “BBF” (2 2 6).

  实际面试遇到了,当时想错了- -,出了门就发现写错了。。
  这道题其实不麻烦,就是在遍历到一个位置 i 的时候,知道前边这个位置 i - 1 为结尾的情况数 pre1,以及 i - 2 位置为结尾的情况数 pre2。那么,当 i 位置不是 0 的时候,自己一个数组成一个字符的情况就是 pre1 种;如果 i 位置是0,那么前边的数只能是 1 或者 2 不然这个 string 就是不合法的,直接返回 0。对于 i - 1 位置和 i 位置组成一个合法字符,也就是 10、11、12 … 19、20、21、22、23、24、25、26 这些情况,a == '1' || (a == '2' && b <= '6'),i 位置情况就要再加上 pre2 即可。每次更新 pre1 之后让 pre2 = 之前的pre1 即可。

bool isValid(char a, char b) {
	return a == '1' || (a == '2' && b <= '6');
}

int numDecodings(string s) {
	const int len = s.length();
	if (s[0] == '0') return 0;
	if (len == 1) return 1;
    // pre1: 前一个位置为结尾的情况, pre2: 前两个位置为结尾的情况
	int pre1 = 1, pre2 = 1;
	for(int i = 1; i < len; ++i) {
		const int pre1_cpy = pre1;
		if (s[i] == '0') {
            if(!isValid(s[i - 1], s[i]))
                return 0;
            pre1 = 0;
        }
		if (isValid(s[i - 1], s[i])) pre1 += pre2;
        pre2 = pre1_cpy;
	}
	return pre1;
}

  用个一位数组dp也可以:

bool isValid(char a, char b) {
	return a == '1' || (a == '2' && b <= '6');
}

int numDecodings(string s) {
	const int n = s.length();
    if(n == 0) return 0;
    if(s[0] == '0') return 0;
    if(n == 1) return 1;
    vector<int> dp(n + 1, 0);
    dp[0] = 1;
    dp[1] = 1;
    for(int i = 2; i <= n; ++i) {
        if(s[i - 1] == '0') {
            if(s[i - 2] != '1' && s[i - 2] != '2')
                return 0;
            dp[i] = dp[i - 2];
        }
        else {
            dp[i] = dp[i - 1];
            if(isValid(s[i - 2], s[i - 1]))
                dp[i] += dp[i - 2];
        }
    }
    return dp[n];
}
LeetCode - 639. Decode Ways II

A message containing letters from A-Z is being encoded to numbers using the following mapping way:
‘A’ -> 1
‘B’ -> 2

‘Z’ -> 26
Beyond that, now the encoded string can also contain the character ‘*’, which can be treated as one of the numbers from 1 to 9.
Given the encoded message containing digits and the character ‘*’, return the total number of ways to decode it.
Also, since the answer may be very large, you should return the output mod 109 + 7.

Example 1: Input: “*” Output: 9
Explanation: The encoded message can be decoded to the string: “A”, “B”, “C”, “D”, “E”, “F”, “G”, “H”, “I”.

Example 2: Input: “1*” Output: 9 + 9 = 18

  比上边的题多了个 '*',就是能够表示 1-9 的任意数。问能有多少种 decode 可能(这道题实际面试没有遇到过,但是也一起总结了)。
  其实就是比上边的要讨论的情况多一些,不过也是每次记录 pre1,更新 pre1,用保存起来的原始 pre1 更新 pre2。

int numDecodings(string s) {
	if (s.empty() || s[0] == '0') return 0;
	const int MOD = 1000000007;
	long long pre1 = s[0] == '*' ? 9 : 1, pre2 = 1;
	for(size_t i = 1; i < s.length(); ++i) {
		const auto pre1_cpy = pre1;	// 保存为后边修改 m2 = m1;
		if(s[i] == '*') {
			pre1 *= 9;	// '*' 表示 1-9
			if (s[i - 1] == '1')
				pre1 = (pre1 + 9 * pre2) % MOD;	 // 11~19
			else if(s[i - 1] == '2')
				pre1 = (pre1 + 6 * pre2) % MOD;	 // 21~26
			else if (s[i - 1] == '*')
				pre1 = (pre1 + 15 * pre2) % MOD; // 9 + 6 = 15
		}
		else {
			if (s[i] == '0')
				pre1 = 0;
			if (s[i - 1] == '1' || (s[i - 1] == '2' && s[i] <= '6'))
				pre1 = (pre1 + pre2) % MOD;
			else if (s[i - 1] == '*')
				pre1 = (pre1 + (s[i] <= '6' ? 2 : 1) * pre2) % MOD;
		}
		pre2 = pre1_cpy;
	}
	return pre1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值