[C++&Rust]LeetCode No.91 解码方法

原贴地址:http://blog.leanote.com/post/dawnmagnet/No.91-解码方法

题目

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

'A' -> 1
'B' -> 2
...
'Z' -> 26

要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,“11106” 可以映射为:

“AAJF” ,将消息分组为 (1-1-10-6)
“KJF” ,将消息分组为 (11-10-6)
注意,消息不能分组为 (1-11-06) ,因为 “06” 不能映射为 “F” ,这是由于 “6” 和 “06” 在映射中并不等价。

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

题目数据保证答案肯定是一个 32 位 的整数。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/decode-ways
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析

dp:动态规划 dfs:深度优先搜索
这个题目是一个分割的题目,常见的做法有dfs和dp。
鉴于dp的性能更好,我们来分析如何使用dp实现这个问题。

动态规划有一个限制,即这个问题能不能被分解成子问题。那我们先假设我们有了子问题的解,也就是对于"11106"来说,我们知道了"1",“11”,“111”,"1110"分别可以有1, 2, 3, 2种方案,那么我们可以靠这些数据推导出"11106"对应的方案数吗?其实对我们来说,需要注意的点就是"0"和"6"两个数字,对于“06”来说,它不能进行组合,所以我们必须将其分割,那么"11106"的分割方案数应该等于"1110"的方案数。
我们对这些情况进行归纳

分割情况公式最后两位举例
只能分割,不能组合f(11106)=f(1110)“06”,“31”
只能组合,不能分割f(11120)=f(111)“20”,“10”
既能组合,也能分割f(11121)=f(1112)+f(111)“15”,“22”
都不行f(11100)=0“30”,“40”

我们将这个情况对应到dp中,设n为当前处理到的长度
如果可以组合 dp[n] += dp[n - 2]
如何可以分割 dp[n] += dp[n - 1]
起始条件是0,边缘条件是dp[-1]是1
那么如何判断组合和分割的情况呢?
我们可以通过观察上表的最后两位举例,来试试推导出按照最后两位判断是否可以判断和分割的情况,我们可以看出,后两位大于等于"10"且小于等于"26"的时候是可以组合的。
最后一位不等于0的时候是可以分割的,我们的代码当然也是基于这个想法。
C++代码

class Solution {
public:
    int numDecodings(string s) {
        vector<int> res = {1, 1};
        int reslen = 2;
        char pre = '0';
        for (auto & ch : s) {
            int tmp = 0;
            if (pre == '1' || (pre == '2' && ch <= '6')) tmp += res[reslen - 2];
            if (ch != '0') tmp += res[reslen - 1];
            res.push_back(tmp);
            reslen++;
            pre = ch;
        }
        return res.back();
    }
};

Rust代码

impl Solution {
    pub fn num_decodings(s: String) -> i32 {
        let mut res = vec![1, 1];
        let mut reslen = 2;
        let mut pre = '0';
        for ch in s.chars() {
            let mut tmp = 0;
            if (pre == '1' || (pre == '2' && ch <= '6')) {
                tmp += res[reslen - 2];
            }
            if (ch != '0') {
                tmp += res[reslen - 1];
            }
            res.push(tmp);
            reslen += 1;
            pre = ch;
        }
        res[reslen - 1]
    }
}

最近可能会出第22期CCF-CSP的题解,上次考崩了,只有320,希望能通过题解更好的提升自己的业务水平!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值