LeetCode--91. 解码方法(动态规划)

解码方法(动态规划)

1. 题目描述

难度:中等
在这里插入图片描述

2. 题目分析

分析这道题,我们要知道以下几点:

  • ‘0’的作用
    • ‘0’出现在字符串开头时,肯定是无法编码的,直接返回0;
    • 如果字符串中出现‘0’字符并且‘0’字符无法和前面的字符匹配,比如‘30’,‘00’等,肯定也是无法编码的,直接返回0;
    • ‘01’不能匹配成1;
  • 特殊的边界条件
    • 如果输入为空字符串,返回0;
    • 如果第一个字符是‘0’, 返回0;
    • 如果字符串的长度为1,并且该字符串不是‘0’,返回1;

这道题的解法可以采用动态规划的算法:

  • 动态规划
    要用动态规划的方法首先要找到动态方程,我们可以根据以下几个条件来进行讨论:
    • 首先确定dp[0]和dp[1]的值,这很简单,不在赘述;
    • 遍历剩余的字符串,并进行分情况讨论:
      • 如果s[i] == ‘0’, 并且s[i]和s[i-1]能够匹配成1-26之间的字母,那么动态方程为:
        dp[i] = dp[i-2]
      • 如果s[i] == ‘0’, 并且s[i]和s[i-1]不能够匹配成1-26之间的字母,直接反回0
      • 如果s[i] != ‘0’, 并且s[i]和s[i-1]能够匹配成1-26之间的字母,动态方程为:
        dp[i] = dp[i-1] + dp[i-2]
      • 如果s[i] != ‘0’, 并且s[i]和s[i-1]不能够匹配成1-26之间的字母,动态方程为:
        dp[i] = dp[i-1]

时间复杂度为O(n).

3. C语言实现

代码如下:

// 匹配函数,判断两个字符是否能匹配成1-26之间的字母
int match(char a, char b){
    if(a == '0') return 0;
    int temp = (a-48)*10 + (b-48);
    if(temp<=26 && temp>=1) return 1;
    else return 0;
}
int numDecodings(char * s){
    int len = strlen(s);
    if(len == 0) return 0;
    if(s[0]=='0') return 0; 
    if(len == 1 ) return 1;
   
    int *dp = (int *)malloc(sizeof(int)*len);
    dp[0] = 1;
    
    if(match(s[0], s[1])) dp[1] = s[1]=='0'?1:2;
    else dp[1] = s[1]=='0'?0:1;

    for(int i = 2; i < len; i++){
        if(s[i] == '0'){
            if(match(s[i-1], s[i])) dp[i] = dp[i-2];
            else return 0;     
        }
        else if(match(s[i-1], s[i])) dp[i] = dp[i-1] + dp[i-2];
        else dp[i] = dp[i-1];
    }
    return dp[len-1];
}

运行结果为:
在这里插入图片描述

发布了164 篇原创文章 · 获赞 189 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_42580947/article/details/105139753