leetcode 639. Decode Ways II

  1. 原理
    动态规划,设dp[i]为[0,i]之间的数字与字母的合法匹配的总数。先计算第i个数字单独匹配一个字母的情况下的数量(设为 xi ),再计算第i-1和i个数字组成一个两位数匹配一个字母的情况下的数量(设为 yi ),则 dp[i]=xidp[i1]+yidp[i2]
  2. 合法匹配的数量列表
    1)1位数

    数字匹配数目
    1-91
    *9

    2) 2位数

    十位数个位数匹配数目
    10-91
    20-61
    *0-62
    *7-91
    1*9
    2*6
    **15
  3. 算法源码

#define MOD_NUMBER 1000000007

#define SYMBOL_CASE(symbol) case symbol:

#define ZERO_CASE \
SYMBOL_CASE('0')

#define ONE_CASE \
SYMBOL_CASE('1')

#define TWO_CASE \
SYMBOL_CASE('2')

#define ONE_SIX_CASE \
ONE_CASE \
TWO_CASE \
SYMBOL_CASE('3') \
SYMBOL_CASE('4') \
SYMBOL_CASE('5') \
SYMBOL_CASE('6')

#define SEVEN_NINE_CASE \
SYMBOL_CASE('7') \
SYMBOL_CASE('8') \
SYMBOL_CASE('9')

#define ONE_NINE_CASE \
ONE_SIX_CASE \
SEVEN_NINE_CASE

#define ZERO_SIX_CASE \
ZERO_CASE \
ONE_SIX_CASE

#define ZERO_NINE_CASE \
ZERO_CASE \
ONE_NINE_CASE

#define ASTERISK_CASE \
SYMBOL_CASE('*')

#define PROCESS_CASE(condition, result) \
condition \
    number = result; \
break;

int num_ways_one_char(char c)
{
    int number = 0;

    switch (c)
    {
        PROCESS_CASE(ONE_NINE_CASE, 1)
        PROCESS_CASE(ASTERISK_CASE, 9)
    default:
        break;
    }

    return number;
}

int num_ways_two_char(char c1, char c2)
{
    int number = 0;

    switch (c1)
    {
        ONE_CASE
            switch (c2)
            {
                PROCESS_CASE(ZERO_NINE_CASE, 1)
                PROCESS_CASE(ASTERISK_CASE, 9)
            default:
                break;
            }
            break;
        TWO_CASE
            switch (c2)
            {
                PROCESS_CASE(ZERO_SIX_CASE, 1)
                PROCESS_CASE(ASTERISK_CASE, 6)
            default:
                break;
            }
            break;
        ASTERISK_CASE
            switch (c2)
            {
                PROCESS_CASE(ZERO_SIX_CASE, 2)
                PROCESS_CASE(SEVEN_NINE_CASE, 1)
                PROCESS_CASE(ASTERISK_CASE, 15)
            default:
                break;
            }
            break;
    default:
        break;
    }

    return number;
}

int numDecodings(char* s) 
{
    int curr_c;
    int pre_c;
    long long curr_res;
    long long pre_res = 1;
    long long next_res;

    curr_c = *(s++);
    curr_res = num_ways_one_char(curr_c);

    pre_c = curr_c;
    curr_c = *(s++);

    if(!curr_c || !curr_res)return curr_res;

    do 
    {
        next_res = ((curr_res * num_ways_one_char(curr_c) % MOD_NUMBER) +
            (pre_res * num_ways_two_char(pre_c, curr_c) % MOD_NUMBER)) % MOD_NUMBER;
        pre_res = curr_res;
        curr_res = next_res;

        if (!curr_res) return 0;

        pre_c = curr_c;
        curr_c = *(s++);
    } while (curr_c);

    return curr_res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值