中等-LeetCode 91.解码方法

题目

来源:解码方法
在这里插入图片描述

示例

在这里插入图片描述

解题思路及代码
1.思路

先讲一下我一开始的思路:新建一个长度跟字符串长度一样的1维数组cur,且每个元素初始化为1,表示单个元素的解码方法数(这个时候没有考虑到数字为0的情况)。从cur的第二个元素开始,若

(s[i-1] < 2) && (s[i-1] > 0) || ((s[i-1] == 2) && s[i] <= 6)

则 cur[i] += cur[i-1]
否则 cur[i] = cur[i-1];
然后发现既没有考虑到中间元素为0时的情况,也没考虑到字符串第一个元素为0的情况,也没考虑到字符串中间连续两个0的情况。。。加了很多判断条件导致代码很冗余。。同时也要考虑到若s[i]为0时,其前一个元素若大于3则返回0,若小于3则只能与s[i]解码为一个数,。。整体来说虽然想到了用动态规划,但是思路不够明确。
整理后的思路
当我们考虑对字符串中某个字符进行解码时,可能出现的情况有
(1) 单独对其进行解码
(2)与前一个字符进行合并解码
(3)无法对其进行解码,即不管是单独解码还是与前一个字符合并解码,都不在题目所给范围内。
经上述分析,要知道累积至当前字符的解码方法总数,只需知道该字符的前两个字符的状态即可。
考虑代码的实现:

  • 若字符串首个字符s[0] = ‘0’,则为第三种情况,无法进行解码,此时直接return 0;
  • 若s[i-1] = ‘1’,
    s[i]若在1-9范围内,则解码方式可以包括情况 (1) 和情况 (2);
    若s[i] = ‘0’,则解码方式只可能是情况(2);
  • 若s[i-2] = ‘2’,
    s[i]若在1-6范围内,则解码方式可以包括情况 (1) 和情况 (2);
    若s[i] = ‘0’,则解码方式只可能是情况(2);
    若s[i] > 6,则解码方式只可能是情况(1);
    经过以上分析,可写出代码如下:
2.代码
var numDecodings = function(s) {
    if(s[0] == '0') {
        return 0;
    }
    var pre = 1;
    var cur = 1;  
    for (var i = 1; i < s.length; i++) {
        var temp = cur;
        if (s[i] == '0') {
            if (s[i-1] == '1' || s[i-1] == '2') {
                cur = pre;
            } else {
                return 0;
            }
        } else if ((s[i-1] == '2' && s[i] >= '1' && s[i] <= '6') || s[i-1] == '1') {
            cur = cur + pre;
        }
        pre = temp;
    }
    return cur;
};

代码解释:先判断字符串首字符是否为’0‘,若为0,无法单独解码也无法合并解码,则可直接返回0了;排除了上述情况之后,考虑到我们之前分析,设当前字符为s[i], 累计至字符s[i]的解码方法总数只与累计至 s[i-1]和 s[i-2]的解码方法总数有关,所以我们只需要创建两个变量,来分别保存s[i-1]和 s[i-2]的状态。
创建变量pre保存s[i-2]的状态,cur保存s[i-1]的状态,因为字符串在只有一个字符且可解码的时候,解码方法只有一种,所以这两个变量均初始化为1。因为我们会在累计解码方法数的过程中不断更新pre和cur的值,遍历至s[i]时,cur会更新为保存s[i]的状态,而pre则会保存s[i-1]的状态,然后接着遍历至下一个字符,所以在这个过程中,我们需要一个中间变量来保存cur在更新前的值,并且将其赋值给pre。
在上述代码实现分析中,我们可以知道:
a. 包括情况 (1) 和情况 (2):

  • s[i-1] = ‘2’ 且 ‘1’ <= s[i] <= ‘6’
  • s[i-1] = ‘1’,且 s[i] != ‘0’
    这种情况下:cur = cur + pre

b. 只可能是情况(2)

  • s[i] = ‘0’,且s[i-1] = ‘1’
  • s[i] = ‘0’,且s[i-1] = ‘2’
    这种情况下:cur = pre

c. 只可能是情况(1)

  • s[i] > 6, 且s[i-2] = ‘2’
    这种情况下:cur的值不进行更新
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值