2018盛大游戏笔试题--(解码方法)

题目描述

一条包含字母 A-Z 的消息通过以下方式进行了编码:
‘A’ -> 1
‘B’ -> 2

‘Z’ -> 26
给定一个只包含数字的非空字符串,请计算解码方法的总数。

示例 :

输入: “12”
输出: 2
解释: 它可以解码为 “AB”(1 2)或者 “L”(12)

算法思路

这道题可以用动态规划的思想来解答,假设f(i)表示当前 i 个字符解码方法的总数,那么可以根据s[i] (当前字符) 的情况来讨论:
    首先举个例子:当前字符串为123时,这三个字符可以组合成若干种解码方法,现在加入一个字符 4 ,由于4和3不能组合在一起,那么对于先前123的各种组合,只能是将4加入合并成一个新的组合而已,不会增加解码方法总数!即此时的 f(i)=f(i-1)。
    s[i]=0时,由于0无法单独解码,只能与其前一个字符组合起来才有意义,且只有当前一个字符为 1,2时才有意义,此时 f(i)=f(i-2); 因为第 i 个字符 和 第 i-1个字符必须捆绑组合在一起解码。
    s[i]=[1-9]时,此时需要判断其与前一个字符的组合情况来讨论,当s[i]与s[i-1]的组合时,f(i)=f(i1)+f(i-2)。即我们可以选择对s[i]单独解码 此f(i)=f(i-1),亦能选择s[i]与s[i-1]组合解码,此时f(i)=f(i-2),所以综合得f(i)=f(i-1)+f(i-2).需要注意的是,当s[i-1]=0时,f(i)=f(i-1)。

  //判断两字符组合之和是否有意义
    bool isNum(char ch1,char ch2)
    {
        int num1=ch1-'0';
        int num2=ch2-'0';
        int sum=num1*10+num2;
        return sum>0 && sum<27 && num1!=0;
    }
    int numDecodings(string s) {
        if(s.empty())  return 0;
        int n=s.size();
        int dp[n]={0};

        //初始化dp[0]
        if(s[0]>='1' && s[0]<='9')
            dp[0]=1;
        else
            return 0;
        for(int i=1;i//判断字符的合法性,每个字符的取值只能在0-9之间
            if(s[i]<'0' || s[i]>'9')
                return 0;
            if(s[i]=='0')
            {
                //当前字符为0时只能与前面字符组合起来才有意义
                if(s[i-1]=='0' || s[i-1]>='3')
                    return 0;
                if(i-2<0)
                    dp[i]=1;
                else
                    dp[i]=dp[i-2];
            }
            else
            {
                //当前字符不为0时,需根据其与前面字符组合的意义分情况讨论
                if(isNum(s[i-1],s[i]))
                {
                    if(i-2<0)
                        dp[i]=2;
                    else
                        dp[i]=dp[i-1]+dp[i-2];
                }
                else
                    dp[i]=dp[i-1];
            }
        }
        return dp[n-1];
    }

你可能感兴趣的:(笔面试算法题题集)